From a3b2a6da25a76f17c73d31def3952feb0fd2296e Mon Sep 17 00:00:00 2001 From: Jeff Davidson Date: Mon, 15 Sep 2014 16:29:06 -0700 Subject: Update protobuf library from 2.3 to 2.6. Copied in all files from the open source protobuf project at commit edc5994525c79cd1919859a370837a6ff7c8e308, removing files which have been renamed (COPYING.txt -> LICENSE, README.txt -> README.md). Removed 2.3 prebuilts, which is an approach that will not work due to incompatibility with the 2.6 runtime. Merged in micro/nano-specific changes in the following files: -Android.mk - updated list of C++/Java sources, bumped versions -java/README.txt - merged in micro/nano instructions, bumped versions -java/pom.xml - merged in micro/nano build rules, set packaging to jar -src/Makefile.am - merged in references to micro/nano generators -src/google/protobuf/compiler/javamicro/javamicro_file.h - imported google/protobuf/compiler/code_generator.h and removed redundant OutputDirectory class. -src/google/protobuf/compiler/javanano/javanano_file.h - same -Replaced instances of vector with std::vector as needed to get libprotobuf-cpp-full to compile. Plan to upstream this fix per discussion with protobuf maintainers. Reran autogen.sh to update ./configure and associated scripts. Change-Id: I949d32fb5126f1c05e2a6ed48f6636a4a9b15a48 --- Android.mk | 46 +- CHANGES.txt | 189 +- CONTRIBUTORS.txt | 6 + COPYING.txt | 33 - LICENSE | 33 + MODULE_LICENSE_BSD_LIKE | 0 Makefile.am | 111 +- Makefile.in | 125 +- README.md | 167 + README.txt | 152 - aclocal.m4 | 40 + autogen.sh | 6 +- benchmarks/ProtoBench.java | 203 + benchmarks/google_message1.dat | Bin 0 -> 228 bytes benchmarks/google_message2.dat | Bin 0 -> 84570 bytes benchmarks/google_size.proto | 136 + benchmarks/google_speed.proto | 136 + benchmarks/readme.txt | 50 + build.gradle | 6 +- config.guess | 504 +-- config.h.in | 6 +- config.sub | 297 +- configure | 4606 +++++++++++-------- configure.ac | 11 +- depcomp | 153 +- editors/proto.vim | 7 +- examples/AddPerson.java | 14 +- examples/list_people.cc | 1 + gtest/build-aux/config.guess | 504 +-- gtest/build-aux/config.sub | 297 +- gtest/build-aux/depcomp | 153 +- gtest/build-aux/install-sh | 32 +- gtest/build-aux/missing | 94 +- install-sh | 32 +- java/README.txt | 6 +- java/pom.xml | 50 +- .../java/com/google/protobuf/AbstractMessage.java | 597 +-- .../com/google/protobuf/AbstractMessageLite.java | 49 +- .../java/com/google/protobuf/AbstractParser.java | 253 ++ .../com/google/protobuf/BoundedByteString.java | 163 + .../main/java/com/google/protobuf/ByteString.java | 935 +++- .../java/com/google/protobuf/CodedInputStream.java | 728 ++- .../com/google/protobuf/CodedOutputStream.java | 280 +- .../main/java/com/google/protobuf/Descriptors.java | 517 ++- .../java/com/google/protobuf/DynamicMessage.java | 205 +- .../main/java/com/google/protobuf/Extension.java | 96 + .../com/google/protobuf/ExtensionRegistry.java | 186 +- .../com/google/protobuf/ExtensionRegistryLite.java | 18 +- .../main/java/com/google/protobuf/FieldSet.java | 431 +- .../java/com/google/protobuf/GeneratedMessage.java | 1292 +++++- .../com/google/protobuf/GeneratedMessageLite.java | 791 +++- .../main/java/com/google/protobuf/Internal.java | 270 ++ .../protobuf/InvalidProtocolBufferException.java | 29 + .../main/java/com/google/protobuf/LazyField.java | 154 + .../java/com/google/protobuf/LazyFieldLite.java | 176 + .../com/google/protobuf/LazyStringArrayList.java | 367 ++ .../java/com/google/protobuf/LazyStringList.java | 163 + .../com/google/protobuf/LiteralByteString.java | 362 ++ .../src/main/java/com/google/protobuf/Message.java | 125 +- .../main/java/com/google/protobuf/MessageLite.java | 87 +- .../com/google/protobuf/MessageLiteOrBuilder.java | 60 + .../java/com/google/protobuf/MessageOrBuilder.java | 143 + .../com/google/protobuf/MessageReflection.java | 931 ++++ java/src/main/java/com/google/protobuf/Parser.java | 261 ++ .../com/google/protobuf/ProtocolStringList.java | 48 + .../com/google/protobuf/RepeatedFieldBuilder.java | 696 +++ .../java/com/google/protobuf/RopeByteString.java | 957 ++++ .../src/main/java/com/google/protobuf/RpcUtil.java | 5 +- .../java/com/google/protobuf/ServiceException.java | 10 +- .../com/google/protobuf/SingleFieldBuilder.java | 241 + .../java/com/google/protobuf/SmallSortedMap.java | 618 +++ .../main/java/com/google/protobuf/TextFormat.java | 1379 ++++-- .../java/com/google/protobuf/UnknownFieldSet.java | 46 +- .../protobuf/UnmodifiableLazyStringList.java | 205 + java/src/main/java/com/google/protobuf/Utf8.java | 349 ++ .../main/java/com/google/protobuf/WireFormat.java | 14 +- .../com/google/protobuf/AbstractMessageTest.java | 82 +- .../com/google/protobuf/BoundedByteStringTest.java | 68 + .../java/com/google/protobuf/ByteStringTest.java | 759 ++++ .../java/com/google/protobuf/CheckUtf8Test.java | 141 + .../com/google/protobuf/CodedInputStreamTest.java | 284 +- .../com/google/protobuf/CodedOutputStreamTest.java | 99 +- .../com/google/protobuf/DeprecatedFieldTest.java | 80 + .../java/com/google/protobuf/DescriptorsTest.java | 257 +- .../com/google/protobuf/DynamicMessageTest.java | 118 +- .../google/protobuf/ForceFieldBuildersPreRun.java | 48 + .../com/google/protobuf/GeneratedMessageTest.java | 920 +++- .../java/com/google/protobuf/IsValidUtf8Test.java | 180 + .../com/google/protobuf/IsValidUtf8TestUtil.java | 421 ++ .../com/google/protobuf/LazyFieldLiteTest.java | 134 + .../java/com/google/protobuf/LazyFieldTest.java | 121 + .../com/google/protobuf/LazyMessageLiteTest.java | 319 ++ .../google/protobuf/LazyStringArrayListTest.java | 174 + .../google/protobuf/LazyStringEndToEndTest.java | 143 + .../com/google/protobuf/LiteEqualsAndHashTest.java | 85 + .../test/java/com/google/protobuf/LiteTest.java | 32 + .../com/google/protobuf/LiteralByteStringTest.java | 396 ++ .../test/java/com/google/protobuf/MessageTest.java | 40 + .../com/google/protobuf/NestedBuildersTest.java | 185 + .../test/java/com/google/protobuf/ParserTest.java | 381 ++ .../google/protobuf/RepeatedFieldBuilderTest.java | 190 + .../protobuf/RopeByteStringSubstringTest.java | 97 + .../com/google/protobuf/RopeByteStringTest.java | 115 + .../test/java/com/google/protobuf/ServiceTest.java | 14 +- .../google/protobuf/SingleFieldBuilderTest.java | 155 + .../com/google/protobuf/SmallSortedMapTest.java | 420 ++ .../com/google/protobuf/TestBadIdentifiers.java | 96 + .../test/java/com/google/protobuf/TestUtil.java | 458 +- .../java/com/google/protobuf/TextFormatTest.java | 420 +- .../com/google/protobuf/UnknownFieldSetTest.java | 216 + .../protobuf/UnmodifiableLazyStringListTest.java | 227 + .../java/com/google/protobuf/WireFormatTest.java | 187 +- .../com/google/protobuf/lazy_fields_lite.proto | 61 + .../com/google/protobuf/lite_equals_and_hash.proto | 55 + .../com/google/protobuf/multiple_files_test.proto | 12 +- .../com/google/protobuf/nested_builders_test.proto | 53 + .../com/google/protobuf/nested_extension.proto | 46 + .../google/protobuf/nested_extension_lite.proto | 48 + .../com/google/protobuf/non_nested_extension.proto | 49 + .../protobuf/non_nested_extension_lite.proto | 50 + .../google/protobuf/outer_class_name_test.proto | 38 + .../google/protobuf/outer_class_name_test2.proto | 42 + .../google/protobuf/outer_class_name_test3.proto | 43 + .../com/google/protobuf/test_bad_identifiers.proto | 157 + .../java/com/google/protobuf/test_check_utf8.proto | 50 + .../com/google/protobuf/test_check_utf8_size.proto | 51 + .../com/google/protobuf/test_custom_options.proto | 43 + .../google/protobuf/test_extra_interfaces.proto | 60 + ltmain.sh | 3967 ++++++++++++----- m4/acx_pthread.m4 | 34 + m4/libtool.m4 | 2386 ++++++---- m4/ltoptions.m4 | 32 +- m4/ltsugar.m4 | 20 +- m4/ltversion.m4 | 12 +- m4/lt~obsolete.m4 | 12 +- m4/stl_hash.m4 | 98 +- missing | 94 +- more_tests/Makefile | 41 + post_process_dist.sh | 60 + prebuilts/Android.mk | 96 - .../arm/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a | Bin 8645812 -> 0 bytes prebuilts/arm/libprotobuf-cpp-2.3.0-full.a | Bin 9764778 -> 0 bytes prebuilts/arm/libprotobuf-cpp-2.3.0-lite.a | Bin 1441604 -> 0 bytes .../arm64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a | Bin 17860234 -> 0 bytes prebuilts/arm64/libprotobuf-cpp-2.3.0-full.a | Bin 22145624 -> 0 bytes prebuilts/arm64/libprotobuf-cpp-2.3.0-lite.a | Bin 2671018 -> 0 bytes prebuilts/host-libprotobuf-java-2.3.0-lite.jar | Bin 51861 -> 0 bytes prebuilts/host-libprotobuf-java-2.3.0-micro.jar | Bin 15431 -> 0 bytes prebuilts/host-libprotobuf-java-2.3.0-nano.jar | Bin 32295 -> 0 bytes prebuilts/libprotobuf-java-2.3.0-lite.jar | Bin 59027 -> 0 bytes prebuilts/libprotobuf-java-2.3.0-micro.jar | Bin 17601 -> 0 bytes prebuilts/libprotobuf-java-2.3.0-nano.jar | Bin 42634 -> 0 bytes .../mips/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a | Bin 10842528 -> 0 bytes prebuilts/mips/libprotobuf-cpp-2.3.0-full.a | Bin 12626042 -> 0 bytes prebuilts/mips/libprotobuf-cpp-2.3.0-lite.a | Bin 1567062 -> 0 bytes .../libprotobuf-cpp-2.3.0-full-gnustl-rtti.a | Bin 18451538 -> 0 bytes prebuilts/mips64/libprotobuf-cpp-2.3.0-full.a | Bin 22309258 -> 0 bytes prebuilts/mips64/libprotobuf-cpp-2.3.0-lite.a | Bin 2590342 -> 0 bytes .../x86/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a | Bin 9828146 -> 0 bytes prebuilts/x86/libprotobuf-cpp-2.3.0-full.a | Bin 13996726 -> 0 bytes prebuilts/x86/libprotobuf-cpp-2.3.0-lite.a | Bin 1607564 -> 0 bytes .../libprotobuf-cpp-2.3.0-full-gnustl-rtti.a | Bin 17080466 -> 0 bytes prebuilts/x86_64/libprotobuf-cpp-2.3.0-full.a | Bin 25589890 -> 0 bytes prebuilts/x86_64/libprotobuf-cpp-2.3.0-lite.a | Bin 2876916 -> 0 bytes protobuf.pc.in | 3 +- python/README.txt | 36 +- python/ez_setup.py | 27 +- python/google/protobuf/descriptor.py | 299 +- python/google/protobuf/descriptor_database.py | 137 + python/google/protobuf/descriptor_pool.py | 643 +++ .../google/protobuf/internal/api_implementation.cc | 139 + .../google/protobuf/internal/api_implementation.py | 89 + .../internal/api_implementation_default_test.py | 63 + python/google/protobuf/internal/containers.py | 59 +- python/google/protobuf/internal/cpp_message.py | 663 +++ python/google/protobuf/internal/decoder.py | 226 +- .../protobuf/internal/descriptor_database_test.py | 63 + .../protobuf/internal/descriptor_pool_test.py | 564 +++ .../protobuf/internal/descriptor_pool_test1.proto | 94 + .../protobuf/internal/descriptor_pool_test2.proto | 70 + .../protobuf/internal/descriptor_python_test.py | 54 + python/google/protobuf/internal/descriptor_test.py | 423 +- python/google/protobuf/internal/encoder.py | 118 +- .../google/protobuf/internal/enum_type_wrapper.py | 89 + .../google/protobuf/internal/factory_test1.proto | 57 + .../google/protobuf/internal/factory_test2.proto | 92 + python/google/protobuf/internal/generator_test.py | 139 +- .../internal/message_factory_python_test.py | 54 + .../protobuf/internal/message_factory_test.py | 131 + .../protobuf/internal/message_python_test.py | 54 + python/google/protobuf/internal/message_test.py | 611 ++- .../protobuf/internal/missing_enum_values.proto | 50 + .../internal/more_extensions_dynamic.proto | 49 + python/google/protobuf/internal/python_message.py | 1247 ++++++ python/google/protobuf/internal/reflection_test.py | 868 +++- .../protobuf/internal/service_reflection_test.py | 6 +- .../protobuf/internal/symbol_database_test.py | 120 + .../protobuf/internal/test_bad_identifiers.proto | 52 + python/google/protobuf/internal/test_util.py | 115 +- .../google/protobuf/internal/text_encoding_test.py | 68 + .../google/protobuf/internal/text_format_test.py | 560 ++- python/google/protobuf/internal/type_checkers.py | 72 +- .../protobuf/internal/unknown_fields_test.py | 231 + .../google/protobuf/internal/wire_format_test.py | 8 +- python/google/protobuf/message.py | 32 +- python/google/protobuf/message_factory.py | 155 + python/google/protobuf/pyext/README | 6 + python/google/protobuf/pyext/__init__.py | 0 python/google/protobuf/pyext/cpp_message.py | 61 + python/google/protobuf/pyext/descriptor.cc | 357 ++ python/google/protobuf/pyext/descriptor.h | 96 + .../google/protobuf/pyext/descriptor_cpp2_test.py | 58 + python/google/protobuf/pyext/extension_dict.cc | 338 ++ python/google/protobuf/pyext/extension_dict.h | 123 + python/google/protobuf/pyext/message.cc | 2561 +++++++++++ python/google/protobuf/pyext/message.h | 305 ++ .../protobuf/pyext/message_factory_cpp2_test.py | 56 + python/google/protobuf/pyext/proto2_api_test.proto | 38 + python/google/protobuf/pyext/python.proto | 66 + python/google/protobuf/pyext/python_protobuf.h | 57 + .../pyext/reflection_cpp2_generated_test.py | 94 + .../protobuf/pyext/repeated_composite_container.cc | 763 ++++ .../protobuf/pyext/repeated_composite_container.h | 172 + .../protobuf/pyext/repeated_scalar_container.cc | 825 ++++ .../protobuf/pyext/repeated_scalar_container.h | 112 + python/google/protobuf/pyext/scoped_pyobject_ptr.h | 95 + python/google/protobuf/reflection.py | 1069 +---- python/google/protobuf/symbol_database.py | 185 + python/google/protobuf/text_encoding.py | 110 + python/google/protobuf/text_format.py | 584 ++- python/setup.py | 157 +- src/Makefile.am | 148 +- src/Makefile.in | 3647 ++++++++------- src/google/protobuf/SEBS | 240 + src/google/protobuf/compiler/code_generator.cc | 19 +- src/google/protobuf/compiler/code_generator.h | 27 +- .../protobuf/compiler/command_line_interface.cc | 510 ++- .../protobuf/compiler/command_line_interface.h | 82 +- .../compiler/command_line_interface_unittest.cc | 331 +- .../compiler/cpp/cpp_bootstrap_unittest.cc | 42 +- src/google/protobuf/compiler/cpp/cpp_enum.cc | 58 +- src/google/protobuf/compiler/cpp/cpp_enum.h | 8 +- src/google/protobuf/compiler/cpp/cpp_enum_field.cc | 98 +- src/google/protobuf/compiler/cpp/cpp_enum_field.h | 25 +- src/google/protobuf/compiler/cpp/cpp_extension.cc | 8 +- src/google/protobuf/compiler/cpp/cpp_extension.h | 7 +- src/google/protobuf/compiler/cpp/cpp_field.cc | 57 +- src/google/protobuf/compiler/cpp/cpp_field.h | 26 +- src/google/protobuf/compiler/cpp/cpp_file.cc | 151 +- src/google/protobuf/compiler/cpp/cpp_file.h | 7 +- src/google/protobuf/compiler/cpp/cpp_generator.cc | 15 +- src/google/protobuf/compiler/cpp/cpp_generator.h | 2 +- src/google/protobuf/compiler/cpp/cpp_helpers.cc | 167 +- src/google/protobuf/compiler/cpp/cpp_helpers.h | 62 +- src/google/protobuf/compiler/cpp/cpp_message.cc | 1327 +++++- src/google/protobuf/compiler/cpp/cpp_message.h | 11 +- .../protobuf/compiler/cpp/cpp_message_field.cc | 125 +- .../protobuf/compiler/cpp/cpp_message_field.h | 25 +- src/google/protobuf/compiler/cpp/cpp_options.h | 58 + .../protobuf/compiler/cpp/cpp_plugin_unittest.cc | 40 +- .../protobuf/compiler/cpp/cpp_primitive_field.cc | 85 +- .../protobuf/compiler/cpp/cpp_primitive_field.h | 26 +- src/google/protobuf/compiler/cpp/cpp_service.cc | 6 +- src/google/protobuf/compiler/cpp/cpp_service.h | 4 +- .../protobuf/compiler/cpp/cpp_string_field.cc | 292 +- .../protobuf/compiler/cpp/cpp_string_field.h | 29 +- .../compiler/cpp/cpp_test_bad_identifiers.proto | 23 + src/google/protobuf/compiler/cpp/cpp_unittest.cc | 876 +++- src/google/protobuf/compiler/cpp/cpp_unittest.h | 51 + src/google/protobuf/compiler/importer.cc | 46 +- src/google/protobuf/compiler/importer.h | 20 +- src/google/protobuf/compiler/importer_unittest.cc | 55 +- src/google/protobuf/compiler/java/java_context.cc | 195 + src/google/protobuf/compiler/java/java_context.h | 95 + .../protobuf/compiler/java/java_doc_comment.cc | 233 + .../protobuf/compiler/java/java_doc_comment.h | 69 + .../compiler/java/java_doc_comment_unittest.cc | 67 + src/google/protobuf/compiler/java/java_enum.cc | 159 +- src/google/protobuf/compiler/java/java_enum.h | 17 +- .../protobuf/compiler/java/java_enum_field.cc | 659 ++- .../protobuf/compiler/java/java_enum_field.h | 81 +- .../protobuf/compiler/java/java_extension.cc | 248 +- src/google/protobuf/compiler/java/java_extension.h | 46 +- src/google/protobuf/compiler/java/java_field.cc | 197 +- src/google/protobuf/compiler/java/java_field.h | 88 +- src/google/protobuf/compiler/java/java_file.cc | 432 +- src/google/protobuf/compiler/java/java_file.h | 36 +- .../protobuf/compiler/java/java_generator.cc | 82 +- src/google/protobuf/compiler/java/java_generator.h | 2 +- .../compiler/java/java_generator_factory.cc | 77 + .../compiler/java/java_generator_factory.h | 101 + src/google/protobuf/compiler/java/java_helpers.cc | 470 +- src/google/protobuf/compiler/java/java_helpers.h | 203 +- .../compiler/java/java_lazy_message_field.cc | 826 ++++ .../compiler/java/java_lazy_message_field.h | 121 + src/google/protobuf/compiler/java/java_message.cc | 1444 ++++-- src/google/protobuf/compiler/java/java_message.h | 62 +- .../protobuf/compiler/java/java_message_field.cc | 1332 +++++- .../protobuf/compiler/java/java_message_field.h | 99 +- .../protobuf/compiler/java/java_name_resolver.cc | 266 ++ .../protobuf/compiler/java/java_name_resolver.h | 124 + .../protobuf/compiler/java/java_plugin_unittest.cc | 41 +- .../protobuf/compiler/java/java_primitive_field.cc | 802 +++- .../protobuf/compiler/java/java_primitive_field.h | 83 +- src/google/protobuf/compiler/java/java_service.cc | 85 +- src/google/protobuf/compiler/java/java_service.h | 38 +- .../compiler/java/java_shared_code_generator.cc | 201 + .../compiler/java/java_shared_code_generator.h | 90 + .../protobuf/compiler/java/java_string_field.cc | 1056 +++++ .../protobuf/compiler/java/java_string_field.h | 160 + .../protobuf/compiler/javamicro/javamicro_file.h | 4 +- .../protobuf/compiler/javanano/javanano_file.h | 4 +- src/google/protobuf/compiler/main.cc | 2 +- .../protobuf/compiler/mock_code_generator.cc | 83 +- src/google/protobuf/compiler/mock_code_generator.h | 13 +- src/google/protobuf/compiler/parser.cc | 1156 +++-- src/google/protobuf/compiler/parser.h | 260 +- src/google/protobuf/compiler/parser_unittest.cc | 1370 +++++- src/google/protobuf/compiler/plugin.cc | 35 +- src/google/protobuf/compiler/plugin.h | 1 - src/google/protobuf/compiler/plugin.pb.cc | 418 +- src/google/protobuf/compiler/plugin.pb.h | 482 +- src/google/protobuf/compiler/plugin.proto | 4 +- .../protobuf/compiler/python/python_generator.cc | 380 +- .../protobuf/compiler/python/python_generator.h | 17 +- .../compiler/python/python_plugin_unittest.cc | 30 +- src/google/protobuf/compiler/subprocess.cc | 39 +- src/google/protobuf/compiler/subprocess.h | 5 +- .../protobuf/compiler/zip_output_unittest.sh | 36 +- src/google/protobuf/compiler/zip_writer.cc | 34 +- src/google/protobuf/compiler/zip_writer.h | 34 +- src/google/protobuf/descriptor.cc | 1479 ++++++- src/google/protobuf/descriptor.h | 356 +- src/google/protobuf/descriptor.pb.cc | 4638 ++++++++++++++------ src/google/protobuf/descriptor.pb.h | 4240 ++++++++++++++---- src/google/protobuf/descriptor.proto | 290 +- src/google/protobuf/descriptor_database.cc | 10 +- src/google/protobuf/descriptor_database.h | 7 +- src/google/protobuf/descriptor_pb2_test.py | 54 + src/google/protobuf/descriptor_unittest.cc | 1709 +++++++- src/google/protobuf/dynamic_message.cc | 260 +- src/google/protobuf/dynamic_message.h | 16 +- src/google/protobuf/dynamic_message_unittest.cc | 68 + src/google/protobuf/extension_set.cc | 634 ++- src/google/protobuf/extension_set.h | 484 +- src/google/protobuf/extension_set_heavy.cc | 301 +- src/google/protobuf/extension_set_unittest.cc | 469 +- src/google/protobuf/generated_enum_reflection.h | 91 + .../protobuf/generated_message_reflection.cc | 634 ++- src/google/protobuf/generated_message_reflection.h | 142 +- .../generated_message_reflection_unittest.cc | 415 +- src/google/protobuf/generated_message_util.cc | 8 + src/google/protobuf/generated_message_util.h | 58 +- src/google/protobuf/io/coded_stream.cc | 162 +- src/google/protobuf/io/coded_stream.h | 216 +- src/google/protobuf/io/coded_stream_inl.h | 11 +- src/google/protobuf/io/coded_stream_unittest.cc | 281 +- src/google/protobuf/io/gzip_stream.cc | 60 +- src/google/protobuf/io/gzip_stream.h | 14 +- src/google/protobuf/io/printer.cc | 18 +- src/google/protobuf/io/printer.h | 6 +- src/google/protobuf/io/printer_unittest.cc | 30 +- src/google/protobuf/io/strtod.cc | 113 + src/google/protobuf/io/strtod.h | 50 + src/google/protobuf/io/tokenizer.cc | 544 ++- src/google/protobuf/io/tokenizer.h | 115 +- src/google/protobuf/io/tokenizer_unittest.cc | 356 +- src/google/protobuf/io/zero_copy_stream.cc | 9 + src/google/protobuf/io/zero_copy_stream.h | 10 + src/google/protobuf/io/zero_copy_stream_impl.cc | 11 +- src/google/protobuf/io/zero_copy_stream_impl.h | 1 + .../protobuf/io/zero_copy_stream_impl_lite.cc | 22 +- .../protobuf/io/zero_copy_stream_impl_lite.h | 14 + .../protobuf/io/zero_copy_stream_unittest.cc | 262 +- src/google/protobuf/lite_unittest.cc | 244 +- src/google/protobuf/message.cc | 53 +- src/google/protobuf/message.h | 262 +- src/google/protobuf/message_lite.cc | 7 +- src/google/protobuf/message_lite.h | 12 +- src/google/protobuf/message_unittest.cc | 152 +- src/google/protobuf/reflection_ops.cc | 23 +- src/google/protobuf/reflection_ops.h | 1 + src/google/protobuf/reflection_ops_unittest.cc | 76 +- src/google/protobuf/repeated_field.cc | 26 +- src/google/protobuf/repeated_field.h | 545 ++- .../protobuf/repeated_field_reflection_unittest.cc | 195 + src/google/protobuf/repeated_field_unittest.cc | 520 ++- src/google/protobuf/stubs/atomicops.h | 216 + .../protobuf/stubs/atomicops_internals_arm64_gcc.h | 325 ++ .../protobuf/stubs/atomicops_internals_arm_gcc.h | 151 + .../protobuf/stubs/atomicops_internals_arm_qnx.h | 146 + .../stubs/atomicops_internals_atomicword_compat.h | 122 + .../stubs/atomicops_internals_generic_gcc.h | 137 + .../protobuf/stubs/atomicops_internals_macosx.h | 225 + .../protobuf/stubs/atomicops_internals_mips_gcc.h | 313 ++ .../protobuf/stubs/atomicops_internals_pnacl.h | 73 + .../protobuf/stubs/atomicops_internals_tsan.h | 219 + .../protobuf/stubs/atomicops_internals_x86_gcc.cc | 137 + .../protobuf/stubs/atomicops_internals_x86_gcc.h | 293 ++ .../protobuf/stubs/atomicops_internals_x86_msvc.cc | 112 + .../protobuf/stubs/atomicops_internals_x86_msvc.h | 150 + src/google/protobuf/stubs/common.cc | 40 +- src/google/protobuf/stubs/common.h | 127 +- src/google/protobuf/stubs/common_unittest.cc | 18 +- src/google/protobuf/stubs/hash.h | 12 + src/google/protobuf/stubs/map_util.h | 771 ++++ src/google/protobuf/stubs/once.cc | 79 +- src/google/protobuf/stubs/once.h | 101 +- src/google/protobuf/stubs/platform_macros.h | 86 + src/google/protobuf/stubs/shared_ptr.h | 470 ++ src/google/protobuf/stubs/stl_util.h | 121 + src/google/protobuf/stubs/stringprintf.cc | 175 + src/google/protobuf/stubs/stringprintf.h | 76 + src/google/protobuf/stubs/stringprintf_unittest.cc | 152 + src/google/protobuf/stubs/strutil.cc | 231 +- src/google/protobuf/stubs/strutil.h | 121 +- src/google/protobuf/stubs/strutil_unittest.cc | 10 - src/google/protobuf/stubs/substitute.cc | 2 +- src/google/protobuf/stubs/template_util.h | 138 + .../protobuf/stubs/template_util_unittest.cc | 130 + src/google/protobuf/stubs/type_traits.h | 336 ++ src/google/protobuf/stubs/type_traits_unittest.cc | 628 +++ src/google/protobuf/test_util.cc | 685 ++- src/google/protobuf/test_util.h | 43 +- src/google/protobuf/test_util_lite.cc | 189 +- src/google/protobuf/testdata/bad_utf8_string | 1 + src/google/protobuf/testdata/golden_message | Bin 487 -> 531 bytes .../testdata/golden_message_oneof_implemented | Bin 0 -> 515 bytes .../testdata/text_format_unittest_data.txt | 18 + ...text_format_unittest_data_oneof_implemented.txt | 129 + .../testdata/text_format_unittest_data_pointy.txt | 134 + .../text_format_unittest_data_pointy_oneof.txt | 129 + .../text_format_unittest_extensions_data.txt | 18 + ...text_format_unittest_extensions_data_pointy.txt | 134 + src/google/protobuf/testing/file.cc | 18 + src/google/protobuf/testing/file.h | 14 + src/google/protobuf/testing/googletest.cc | 11 +- src/google/protobuf/testing/googletest.h | 16 +- src/google/protobuf/text_format.cc | 869 +++- src/google/protobuf/text_format.h | 245 +- src/google/protobuf/text_format_unittest.cc | 459 +- src/google/protobuf/unittest.proto | 249 ++ src/google/protobuf/unittest_custom_options.proto | 118 + src/google/protobuf/unittest_import.proto | 3 + src/google/protobuf/unittest_import_lite.proto | 2 + src/google/protobuf/unittest_import_public.proto | 40 + .../protobuf/unittest_import_public_lite.proto | 42 + src/google/protobuf/unittest_lite.proto | 72 + src/google/protobuf/unittest_mset.proto | 11 + .../protobuf/unittest_no_generic_services.proto | 5 +- src/google/protobuf/unittest_optimize_for.proto | 7 +- src/google/protobuf/unknown_field_set.cc | 97 +- src/google/protobuf/unknown_field_set.h | 90 +- src/google/protobuf/unknown_field_set_unittest.cc | 95 +- src/google/protobuf/wire_format.cc | 104 +- src/google/protobuf/wire_format.h | 42 +- src/google/protobuf/wire_format_lite.cc | 126 +- src/google/protobuf/wire_format_lite.h | 49 +- src/google/protobuf/wire_format_lite_inl.h | 221 +- src/google/protobuf/wire_format_unittest.cc | 247 +- vsprojects/extract_includes.bat | 8 + vsprojects/libprotobuf-lite.vcproj | 38 +- vsprojects/libprotobuf.vcproj | 46 +- vsprojects/libprotoc.vcproj | 872 ++-- vsprojects/lite-test.vcproj | 38 +- vsprojects/protobuf.sln | 184 +- vsprojects/protoc.vcproj | 384 +- vsprojects/test_plugin.vcproj | 38 +- vsprojects/tests.vcproj | 62 +- 469 files changed, 94138 insertions(+), 18254 deletions(-) delete mode 100644 COPYING.txt create mode 100644 LICENSE delete mode 100644 MODULE_LICENSE_BSD_LIKE create mode 100644 README.md delete mode 100644 README.txt create mode 100644 benchmarks/ProtoBench.java create mode 100644 benchmarks/google_message1.dat create mode 100644 benchmarks/google_message2.dat create mode 100644 benchmarks/google_size.proto create mode 100644 benchmarks/google_speed.proto create mode 100644 benchmarks/readme.txt create mode 100644 java/src/main/java/com/google/protobuf/AbstractParser.java create mode 100644 java/src/main/java/com/google/protobuf/BoundedByteString.java create mode 100644 java/src/main/java/com/google/protobuf/Extension.java create mode 100644 java/src/main/java/com/google/protobuf/LazyField.java create mode 100644 java/src/main/java/com/google/protobuf/LazyFieldLite.java create mode 100644 java/src/main/java/com/google/protobuf/LazyStringArrayList.java create mode 100644 java/src/main/java/com/google/protobuf/LazyStringList.java create mode 100644 java/src/main/java/com/google/protobuf/LiteralByteString.java create mode 100644 java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java create mode 100644 java/src/main/java/com/google/protobuf/MessageOrBuilder.java create mode 100644 java/src/main/java/com/google/protobuf/MessageReflection.java create mode 100644 java/src/main/java/com/google/protobuf/Parser.java create mode 100644 java/src/main/java/com/google/protobuf/ProtocolStringList.java create mode 100644 java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java create mode 100644 java/src/main/java/com/google/protobuf/RopeByteString.java create mode 100644 java/src/main/java/com/google/protobuf/SingleFieldBuilder.java create mode 100644 java/src/main/java/com/google/protobuf/SmallSortedMap.java create mode 100644 java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java create mode 100644 java/src/main/java/com/google/protobuf/Utf8.java create mode 100644 java/src/test/java/com/google/protobuf/BoundedByteStringTest.java create mode 100644 java/src/test/java/com/google/protobuf/ByteStringTest.java create mode 100644 java/src/test/java/com/google/protobuf/CheckUtf8Test.java create mode 100644 java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java create mode 100644 java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java create mode 100644 java/src/test/java/com/google/protobuf/IsValidUtf8Test.java create mode 100644 java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java create mode 100644 java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java create mode 100644 java/src/test/java/com/google/protobuf/LazyFieldTest.java create mode 100644 java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java create mode 100644 java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java create mode 100644 java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java create mode 100644 java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java create mode 100644 java/src/test/java/com/google/protobuf/LiteralByteStringTest.java create mode 100644 java/src/test/java/com/google/protobuf/NestedBuildersTest.java create mode 100644 java/src/test/java/com/google/protobuf/ParserTest.java create mode 100644 java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java create mode 100644 java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java create mode 100644 java/src/test/java/com/google/protobuf/RopeByteStringTest.java create mode 100644 java/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java create mode 100644 java/src/test/java/com/google/protobuf/SmallSortedMapTest.java create mode 100644 java/src/test/java/com/google/protobuf/TestBadIdentifiers.java create mode 100644 java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java create mode 100644 java/src/test/java/com/google/protobuf/lazy_fields_lite.proto create mode 100644 java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto create mode 100644 java/src/test/java/com/google/protobuf/nested_builders_test.proto create mode 100644 java/src/test/java/com/google/protobuf/nested_extension.proto create mode 100644 java/src/test/java/com/google/protobuf/nested_extension_lite.proto create mode 100644 java/src/test/java/com/google/protobuf/non_nested_extension.proto create mode 100644 java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto create mode 100644 java/src/test/java/com/google/protobuf/outer_class_name_test.proto create mode 100644 java/src/test/java/com/google/protobuf/outer_class_name_test2.proto create mode 100644 java/src/test/java/com/google/protobuf/outer_class_name_test3.proto create mode 100644 java/src/test/java/com/google/protobuf/test_bad_identifiers.proto create mode 100644 java/src/test/java/com/google/protobuf/test_check_utf8.proto create mode 100644 java/src/test/java/com/google/protobuf/test_check_utf8_size.proto create mode 100644 java/src/test/java/com/google/protobuf/test_custom_options.proto create mode 100644 java/src/test/java/com/google/protobuf/test_extra_interfaces.proto mode change 100755 => 100644 ltmain.sh create mode 100755 more_tests/Makefile create mode 100755 post_process_dist.sh delete mode 100644 prebuilts/Android.mk delete mode 100644 prebuilts/arm/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a delete mode 100644 prebuilts/arm/libprotobuf-cpp-2.3.0-full.a delete mode 100644 prebuilts/arm/libprotobuf-cpp-2.3.0-lite.a delete mode 100644 prebuilts/arm64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a delete mode 100644 prebuilts/arm64/libprotobuf-cpp-2.3.0-full.a delete mode 100644 prebuilts/arm64/libprotobuf-cpp-2.3.0-lite.a delete mode 100644 prebuilts/host-libprotobuf-java-2.3.0-lite.jar delete mode 100644 prebuilts/host-libprotobuf-java-2.3.0-micro.jar delete mode 100644 prebuilts/host-libprotobuf-java-2.3.0-nano.jar delete mode 100644 prebuilts/libprotobuf-java-2.3.0-lite.jar delete mode 100644 prebuilts/libprotobuf-java-2.3.0-micro.jar delete mode 100644 prebuilts/libprotobuf-java-2.3.0-nano.jar delete mode 100644 prebuilts/mips/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a delete mode 100644 prebuilts/mips/libprotobuf-cpp-2.3.0-full.a delete mode 100644 prebuilts/mips/libprotobuf-cpp-2.3.0-lite.a delete mode 100644 prebuilts/mips64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a delete mode 100644 prebuilts/mips64/libprotobuf-cpp-2.3.0-full.a delete mode 100644 prebuilts/mips64/libprotobuf-cpp-2.3.0-lite.a delete mode 100644 prebuilts/x86/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a delete mode 100644 prebuilts/x86/libprotobuf-cpp-2.3.0-full.a delete mode 100644 prebuilts/x86/libprotobuf-cpp-2.3.0-lite.a delete mode 100644 prebuilts/x86_64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a delete mode 100644 prebuilts/x86_64/libprotobuf-cpp-2.3.0-full.a delete mode 100644 prebuilts/x86_64/libprotobuf-cpp-2.3.0-lite.a create mode 100644 python/google/protobuf/descriptor_database.py create mode 100644 python/google/protobuf/descriptor_pool.py create mode 100644 python/google/protobuf/internal/api_implementation.cc create mode 100755 python/google/protobuf/internal/api_implementation.py create mode 100644 python/google/protobuf/internal/api_implementation_default_test.py create mode 100755 python/google/protobuf/internal/cpp_message.py create mode 100644 python/google/protobuf/internal/descriptor_database_test.py create mode 100644 python/google/protobuf/internal/descriptor_pool_test.py create mode 100644 python/google/protobuf/internal/descriptor_pool_test1.proto create mode 100644 python/google/protobuf/internal/descriptor_pool_test2.proto create mode 100644 python/google/protobuf/internal/descriptor_python_test.py create mode 100644 python/google/protobuf/internal/enum_type_wrapper.py create mode 100644 python/google/protobuf/internal/factory_test1.proto create mode 100644 python/google/protobuf/internal/factory_test2.proto create mode 100644 python/google/protobuf/internal/message_factory_python_test.py create mode 100644 python/google/protobuf/internal/message_factory_test.py create mode 100644 python/google/protobuf/internal/message_python_test.py create mode 100644 python/google/protobuf/internal/missing_enum_values.proto create mode 100644 python/google/protobuf/internal/more_extensions_dynamic.proto create mode 100755 python/google/protobuf/internal/python_message.py create mode 100644 python/google/protobuf/internal/symbol_database_test.py create mode 100644 python/google/protobuf/internal/test_bad_identifiers.proto create mode 100755 python/google/protobuf/internal/text_encoding_test.py create mode 100755 python/google/protobuf/internal/unknown_fields_test.py create mode 100644 python/google/protobuf/message_factory.py create mode 100644 python/google/protobuf/pyext/README create mode 100644 python/google/protobuf/pyext/__init__.py create mode 100644 python/google/protobuf/pyext/cpp_message.py create mode 100644 python/google/protobuf/pyext/descriptor.cc create mode 100644 python/google/protobuf/pyext/descriptor.h create mode 100644 python/google/protobuf/pyext/descriptor_cpp2_test.py create mode 100644 python/google/protobuf/pyext/extension_dict.cc create mode 100644 python/google/protobuf/pyext/extension_dict.h create mode 100644 python/google/protobuf/pyext/message.cc create mode 100644 python/google/protobuf/pyext/message.h create mode 100644 python/google/protobuf/pyext/message_factory_cpp2_test.py create mode 100644 python/google/protobuf/pyext/proto2_api_test.proto create mode 100644 python/google/protobuf/pyext/python.proto create mode 100644 python/google/protobuf/pyext/python_protobuf.h create mode 100755 python/google/protobuf/pyext/reflection_cpp2_generated_test.py create mode 100644 python/google/protobuf/pyext/repeated_composite_container.cc create mode 100644 python/google/protobuf/pyext/repeated_composite_container.h create mode 100644 python/google/protobuf/pyext/repeated_scalar_container.cc create mode 100644 python/google/protobuf/pyext/repeated_scalar_container.h create mode 100644 python/google/protobuf/pyext/scoped_pyobject_ptr.h create mode 100644 python/google/protobuf/symbol_database.py create mode 100644 python/google/protobuf/text_encoding.py create mode 100644 src/google/protobuf/SEBS create mode 100644 src/google/protobuf/compiler/cpp/cpp_options.h create mode 100644 src/google/protobuf/compiler/cpp/cpp_unittest.h create mode 100644 src/google/protobuf/compiler/java/java_context.cc create mode 100644 src/google/protobuf/compiler/java/java_context.h create mode 100644 src/google/protobuf/compiler/java/java_doc_comment.cc create mode 100644 src/google/protobuf/compiler/java/java_doc_comment.h create mode 100644 src/google/protobuf/compiler/java/java_doc_comment_unittest.cc create mode 100644 src/google/protobuf/compiler/java/java_generator_factory.cc create mode 100644 src/google/protobuf/compiler/java/java_generator_factory.h create mode 100644 src/google/protobuf/compiler/java/java_lazy_message_field.cc create mode 100644 src/google/protobuf/compiler/java/java_lazy_message_field.h create mode 100644 src/google/protobuf/compiler/java/java_name_resolver.cc create mode 100644 src/google/protobuf/compiler/java/java_name_resolver.h create mode 100644 src/google/protobuf/compiler/java/java_shared_code_generator.cc create mode 100644 src/google/protobuf/compiler/java/java_shared_code_generator.h create mode 100644 src/google/protobuf/compiler/java/java_string_field.cc create mode 100644 src/google/protobuf/compiler/java/java_string_field.h create mode 100644 src/google/protobuf/descriptor_pb2_test.py create mode 100644 src/google/protobuf/generated_enum_reflection.h create mode 100644 src/google/protobuf/io/strtod.cc create mode 100644 src/google/protobuf/io/strtod.h create mode 100644 src/google/protobuf/repeated_field_reflection_unittest.cc create mode 100644 src/google/protobuf/stubs/atomicops.h create mode 100644 src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h create mode 100644 src/google/protobuf/stubs/atomicops_internals_arm_gcc.h create mode 100644 src/google/protobuf/stubs/atomicops_internals_arm_qnx.h create mode 100644 src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h create mode 100644 src/google/protobuf/stubs/atomicops_internals_generic_gcc.h create mode 100644 src/google/protobuf/stubs/atomicops_internals_macosx.h create mode 100644 src/google/protobuf/stubs/atomicops_internals_mips_gcc.h create mode 100644 src/google/protobuf/stubs/atomicops_internals_pnacl.h create mode 100644 src/google/protobuf/stubs/atomicops_internals_tsan.h create mode 100644 src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc create mode 100644 src/google/protobuf/stubs/atomicops_internals_x86_gcc.h create mode 100644 src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc create mode 100644 src/google/protobuf/stubs/atomicops_internals_x86_msvc.h create mode 100644 src/google/protobuf/stubs/map_util.h create mode 100644 src/google/protobuf/stubs/platform_macros.h create mode 100644 src/google/protobuf/stubs/shared_ptr.h create mode 100644 src/google/protobuf/stubs/stl_util.h create mode 100644 src/google/protobuf/stubs/stringprintf.cc create mode 100644 src/google/protobuf/stubs/stringprintf.h create mode 100644 src/google/protobuf/stubs/stringprintf_unittest.cc create mode 100644 src/google/protobuf/stubs/template_util.h create mode 100644 src/google/protobuf/stubs/template_util_unittest.cc create mode 100644 src/google/protobuf/stubs/type_traits.h create mode 100644 src/google/protobuf/stubs/type_traits_unittest.cc create mode 100644 src/google/protobuf/testdata/bad_utf8_string create mode 100644 src/google/protobuf/testdata/golden_message_oneof_implemented create mode 100644 src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt create mode 100644 src/google/protobuf/testdata/text_format_unittest_data_pointy.txt create mode 100644 src/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt create mode 100644 src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt create mode 100644 src/google/protobuf/unittest_import_public.proto create mode 100644 src/google/protobuf/unittest_import_public_lite.proto diff --git a/Android.mk b/Android.mk index 18bdd09..609d5a3 100644 --- a/Android.mk +++ b/Android.mk @@ -16,15 +16,18 @@ LOCAL_PATH := $(call my-dir) -IGNORED_WARNINGS := -Wno-sign-compare -Wno-unused-parameter -Wno-sign-promo +IGNORED_WARNINGS := -Wno-sign-compare -Wno-unused-parameter -Wno-sign-promo -Wno-error=return-type CC_LITE_SRC_FILES := \ + src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc \ + src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc \ src/google/protobuf/stubs/common.cc \ src/google/protobuf/stubs/once.cc \ - src/google/protobuf/stubs/hash.cc \ src/google/protobuf/stubs/hash.h \ - src/google/protobuf/stubs/map-util.h \ - src/google/protobuf/stubs/stl_util-inl.h \ + src/google/protobuf/stubs/map_util.h \ + src/google/protobuf/stubs/shared_ptr.h \ + src/google/protobuf/stubs/stringprintf.cc \ + src/google/protobuf/stubs/stringprintf.h \ src/google/protobuf/extension_set.cc \ src/google/protobuf/generated_message_util.cc \ src/google/protobuf/message_lite.cc \ @@ -44,10 +47,24 @@ JAVA_LITE_SRC_FILES := \ java/src/main/java/com/google/protobuf/CodedInputStream.java \ java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java \ java/src/main/java/com/google/protobuf/AbstractMessageLite.java \ + java/src/main/java/com/google/protobuf/AbstractParser.java \ java/src/main/java/com/google/protobuf/FieldSet.java \ java/src/main/java/com/google/protobuf/Internal.java \ java/src/main/java/com/google/protobuf/WireFormat.java \ - java/src/main/java/com/google/protobuf/GeneratedMessageLite.java + java/src/main/java/com/google/protobuf/GeneratedMessageLite.java \ + java/src/main/java/com/google/protobuf/BoundedByteString.java \ + java/src/main/java/com/google/protobuf/LazyField.java \ + java/src/main/java/com/google/protobuf/LazyFieldLite.java \ + java/src/main/java/com/google/protobuf/LazyStringList.java \ + java/src/main/java/com/google/protobuf/LazyStringArrayList.java \ + java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java \ + java/src/main/java/com/google/protobuf/LiteralByteString.java \ + java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java \ + java/src/main/java/com/google/protobuf/Parser.java \ + java/src/main/java/com/google/protobuf/ProtocolStringList.java \ + java/src/main/java/com/google/protobuf/RopeByteString.java \ + java/src/main/java/com/google/protobuf/SmallSortedMap.java \ + java/src/main/java/com/google/protobuf/Utf8.java COMPILER_SRC_FILES := \ src/google/protobuf/descriptor.cc \ @@ -88,17 +105,24 @@ COMPILER_SRC_FILES := \ src/google/protobuf/compiler/cpp/cpp_primitive_field.cc \ src/google/protobuf/compiler/cpp/cpp_service.cc \ src/google/protobuf/compiler/cpp/cpp_string_field.cc \ + src/google/protobuf/compiler/java/java_context.cc \ src/google/protobuf/compiler/java/java_enum.cc \ src/google/protobuf/compiler/java/java_enum_field.cc \ src/google/protobuf/compiler/java/java_extension.cc \ src/google/protobuf/compiler/java/java_field.cc \ src/google/protobuf/compiler/java/java_file.cc \ src/google/protobuf/compiler/java/java_generator.cc \ + src/google/protobuf/compiler/java/java_generator_factory.cc \ src/google/protobuf/compiler/java/java_helpers.cc \ + src/google/protobuf/compiler/java/java_lazy_message_field.cc \ src/google/protobuf/compiler/java/java_message.cc \ src/google/protobuf/compiler/java/java_message_field.cc \ + src/google/protobuf/compiler/java/java_name_resolver.cc \ src/google/protobuf/compiler/java/java_primitive_field.cc \ + src/google/protobuf/compiler/java/java_shared_code_generator.cc \ src/google/protobuf/compiler/java/java_service.cc \ + src/google/protobuf/compiler/java/java_string_field.cc \ + src/google/protobuf/compiler/java/java_doc_comment.cc \ src/google/protobuf/compiler/javamicro/javamicro_enum.cc \ src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc \ src/google/protobuf/compiler/javamicro/javamicro_field.cc \ @@ -122,16 +146,19 @@ COMPILER_SRC_FILES := \ src/google/protobuf/io/coded_stream.cc \ src/google/protobuf/io/gzip_stream.cc \ src/google/protobuf/io/printer.cc \ + src/google/protobuf/io/strtod.cc \ src/google/protobuf/io/tokenizer.cc \ src/google/protobuf/io/zero_copy_stream.cc \ src/google/protobuf/io/zero_copy_stream_impl.cc \ src/google/protobuf/io/zero_copy_stream_impl_lite.cc \ + src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc \ + src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc \ src/google/protobuf/stubs/common.cc \ - src/google/protobuf/stubs/hash.cc \ src/google/protobuf/stubs/once.cc \ src/google/protobuf/stubs/structurally_valid.cc \ src/google/protobuf/stubs/strutil.cc \ - src/google/protobuf/stubs/substitute.cc + src/google/protobuf/stubs/substitute.cc \ + src/google/protobuf/stubs/stringprintf.cc # Java nano library (for device-side users) # ======================================================= @@ -186,7 +213,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := libprotobuf-java-lite LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := 8 +LOCAL_SDK_VERSION := 9 LOCAL_SRC_FILES := $(JAVA_LITE_SRC_FILES) @@ -285,6 +312,7 @@ protobuf_cc_full_src_files := \ src/google/protobuf/wire_format.cc \ src/google/protobuf/io/gzip_stream.cc \ src/google/protobuf/io/printer.cc \ + src/google/protobuf/io/strtod.cc \ src/google/protobuf/io/tokenizer.cc \ src/google/protobuf/io/zero_copy_stream_impl.cc \ src/google/protobuf/compiler/importer.cc \ @@ -482,5 +510,3 @@ LOCAL_DEX_PREOPT := false include $(BUILD_PACKAGE) -# 2.3.0 prebuilts for backwards compatibility. -include $(LOCAL_PATH)/prebuilts/Android.mk diff --git a/CHANGES.txt b/CHANGES.txt index eebd57d..214d8d9 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,191 @@ -2009-01-08 version 2.3.0: +2014-08-15 version 2.6.0: + + General + * Added oneofs(unions) feature. Fields in the same oneof will share + memory and at most one field can be set at the same time. Use the + oneof keyword to define a oneof like: + message SampleMessage { + oneof test_oneof { + string name = 4; + YourMessage sub_message = 9; + } + } + * Files, services, enums, messages, methods and enum values can be marked + as deprecated now. + * Added Support for list values, including lists of mesaages, when + parsing text-formatted protos in C++ and Java. + For example: foo: [1, 2, 3] + + C++ + * Enhanced customization on TestFormat printing. + * Added SwapFields() in reflection API to swap a subset of fields. + Added SetAllocatedMessage() in reflection API. + * Repeated primitive extensions are now packable. The + [packed=true] option only affects serializers. Therefore, it is + possible to switch a repeated extension field to packed format + without breaking backwards-compatibility. + * Various speed optimizations. + + Java + * writeTo() method in ByteString can now write a substring to an + output stream. Added endWith() method for ByteString. + * ByteString and ByteBuffer are now supported in CodedInputStream + and CodedOutputStream. + * java_generate_equals_and_hash can now be used with the LITE_RUNTIME. + + Python + * A new C++-backed extension module (aka "cpp api v2") that replaces the + old ("cpp api v1") one. Much faster than the pure Python code. This one + resolves many bugs and is recommended for general use over the + pure Python when possible. + * Descriptors now have enum_types_by_name and extension_types_by_name dict + attributes. + * Support for Python 3. + +2013-02-27 version 2.5.0: + + General + * New notion "import public" that allows a proto file to forward the content + it imports to its importers. For example, + // foo.proto + import public "bar.proto"; + import "baz.proto"; + + // qux.proto + import "foo.proto"; + // Stuff defined in bar.proto may be used in this file, but stuff from + // baz.proto may NOT be used without importing it explicitly. + This is useful for moving proto files. To move a proto file, just leave + a single "import public" in the old proto file. + * New enum option "allow_alias" that specifies whether different symbols can + be assigned the same numeric value. Default value is "true". Setting it to + false causes the compiler to reject enum definitions where multiple symbols + have the same numeric value. + Note: We plan to flip the default value to "false" in a future release. + Projects using enum aliases should set the option to "true" in their .proto + files. + + C++ + * New generated method set_allocated_foo(Type* foo) for message and string + fields. This method allows you to set the field to a pre-allocated object + and the containing message takes the ownership of that object. + * Added SetAllocatedExtension() and ReleaseExtension() to extensions API. + * Custom options are now formatted correctly when descriptors are printed in + text format. + * Various speed optimizations. + + Java + * Comments in proto files are now collected and put into generated code as + comments for corresponding classes and data members. + * Added Parser to parse directly into messages without a Builder. For + example, + Foo foo = Foo.PARSER.ParseFrom(input); + Using Parser is ~25% faster than using Builder to parse messages. + * Added getters/setters to access the underlying ByteString of a string field + directly. + * ByteString now supports more operations: substring(), prepend(), and + append(). The implementation of ByteString uses a binary tree structure + to support these operations efficiently. + * New method findInitializationErrors() that lists all missing required + fields. + * Various code size and speed optimizations. + + Python + * Added support for dynamic message creation. DescriptorDatabase, + DescriptorPool, and MessageFactory work like their C++ couterparts to + simplify Descriptor construction from *DescriptorProtos, and MessageFactory + provides a message instance from a Descriptor. + * Added pickle support for protobuf messages. + * Unknown fields are now preserved after parsing. + * Fixed bug where custom options were not correctly populated. Custom + options can be accessed now. + * Added EnumTypeWrapper that provides better accessibility to enum types. + * Added ParseMessage(descriptor, bytes) to generate a new Message instance + from a descriptor and a byte string. + +2011-05-01 version 2.4.1: + + C++ + * Fixed the frendship problem for old compilers to make the library now gcc 3 + compatible again. + * Fixed vcprojects/extract_includes.bat to extract compiler/plugin.h. + + Java + * Removed usages of JDK 1.6 only features to make the library now JDK 1.5 + compatible again. + * Fixed a bug about negative enum values. + * serialVersionUID is now defined in generated messages for java serializing. + * Fixed protoc to use java.lang.Object, which makes "Object" now a valid + message name again. + + Python + * Experimental C++ implementation now requires C++ protobuf library installed. + See the README.txt in the python directory for details. + +2011-02-02 version 2.4.0: + + General + * The RPC (cc|java|py)_generic_services default value is now false instead of + true. + * Custom options can have aggregate types. For example, + message MyOption { + optional string comment = 1; + optional string author = 2; + } + extend google.protobuf.FieldOptions { + optional MyOption myoption = 12345; + } + This option can now be set as follows: + message SomeType { + optional int32 field = 1 [(myoption) = { comment:'x' author:'y' }]; + } + + C++ + * Various speed and code size optimizations. + * Added a release_foo() method on string and message fields. + * Fixed gzip_output_stream sub-stream handling. + + Java + * Builders now maintain sub-builders for sub-messages. Use getFooBuilder() to + get the builder for the sub-message "foo". This allows you to repeatedly + modify deeply-nested sub-messages without rebuilding them. + * Builder.build() no longer invalidates the Builder for generated messages + (You may continue to modify it and then build another message). + * Code generator will generate efficient equals() and hashCode() + implementations if new option java_generate_equals_and_hash is enabled. + (Otherwise, reflection-based implementations are used.) + * Generated messages now implement Serializable. + * Fields with [deprecated=true] will be marked with @Deprecated in Java. + * Added lazy conversion of UTF-8 encoded strings to String objects to improve + performance. + * Various optimizations. + * Enum value can be accessed directly, instead of calling getNumber() on the + enum member. + * For each enum value, an integer constant is also generated with the suffix + _VALUE. + + Python + * Added an experimental C++ implementation for Python messages via a Python + extension. Implementation type is controlled by an environment variable + PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION (valid values: "cpp" and "python") + The default value is currently "python" but will be changed to "cpp" in + future release. + * Improved performance on message instantiation significantly. + Most of the work on message instantiation is done just once per message + class, instead of once per message instance. + * Improved performance on text message parsing. + * Allow add() to forward keyword arguments to the concrete class. + E.g. instead of + item = repeated_field.add() + item.foo = bar + item.baz = quux + You can do: + repeated_field.add(foo=bar, baz=quux) + * Added a sort() interface to the BaseContainer. + * Added an extend() method to repeated composite fields. + * Added UTF8 debug string support. + +2010-01-08 version 2.3.0: General * Parsers for repeated numeric fields now always accept both packed and diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index a20efc4..b39ec30 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -80,5 +80,11 @@ Patch contributors: * Fixes for Solaris 10 32/64-bit confusion. Evan Jones * Optimize Java serialization code when writing a small message to a stream. + * Optimize Java serialization of strings so that UTF-8 encoding happens only + once per string per serialization call. + * Clean up some Java warnings. + * Fix bug with permanent callbacks that delete themselves when run. Michael Kucharski * Added CodedInputStream.getTotalBytesRead(). + Kacper Kowalik + * Fixed m4/acx_pthread.m4 problem for some Linux distributions. diff --git a/COPYING.txt b/COPYING.txt deleted file mode 100644 index 705db57..0000000 --- a/COPYING.txt +++ /dev/null @@ -1,33 +0,0 @@ -Copyright 2008, 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. - -Code generated by the Protocol Buffer compiler is owned by the owner -of the input file used when generating it. This code is not -standalone and requires a support library to be linked with it. This -support library is itself covered by the above license. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..705db57 --- /dev/null +++ b/LICENSE @@ -0,0 +1,33 @@ +Copyright 2008, 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. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. diff --git a/MODULE_LICENSE_BSD_LIKE b/MODULE_LICENSE_BSD_LIKE deleted file mode 100644 index e69de29..0000000 diff --git a/Makefile.am b/Makefile.am index b65daee..24e5e55 100644 --- a/Makefile.am +++ b/Makefile.am @@ -38,9 +38,9 @@ pkgconfig_DATA = protobuf.pc protobuf-lite.pc EXTRA_DIST = \ autogen.sh \ generate_descriptor_proto.sh \ - README.txt \ + README.md \ INSTALL.txt \ - COPYING.txt \ + LICENSE \ CONTRIBUTORS.txt \ CHANGES.txt \ editors/README.txt \ @@ -69,13 +69,16 @@ EXTRA_DIST = \ examples/list_people.py \ java/src/main/java/com/google/protobuf/AbstractMessage.java \ java/src/main/java/com/google/protobuf/AbstractMessageLite.java \ + java/src/main/java/com/google/protobuf/AbstractParser.java \ java/src/main/java/com/google/protobuf/BlockingRpcChannel.java \ java/src/main/java/com/google/protobuf/BlockingService.java \ + java/src/main/java/com/google/protobuf/BoundedByteString.java \ java/src/main/java/com/google/protobuf/ByteString.java \ java/src/main/java/com/google/protobuf/CodedInputStream.java \ java/src/main/java/com/google/protobuf/CodedOutputStream.java \ java/src/main/java/com/google/protobuf/Descriptors.java \ java/src/main/java/com/google/protobuf/DynamicMessage.java \ + java/src/main/java/com/google/protobuf/Extension.java \ java/src/main/java/com/google/protobuf/ExtensionRegistry.java \ java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java \ java/src/main/java/com/google/protobuf/FieldSet.java \ @@ -83,57 +86,157 @@ EXTRA_DIST = \ java/src/main/java/com/google/protobuf/GeneratedMessageLite.java \ java/src/main/java/com/google/protobuf/Internal.java \ java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \ + java/src/main/java/com/google/protobuf/LazyField.java \ + java/src/main/java/com/google/protobuf/LazyFieldLite.java \ + java/src/main/java/com/google/protobuf/LazyStringArrayList.java \ + java/src/main/java/com/google/protobuf/LazyStringList.java \ + java/src/main/java/com/google/protobuf/LiteralByteString.java \ java/src/main/java/com/google/protobuf/Message.java \ java/src/main/java/com/google/protobuf/MessageLite.java \ + java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java \ + java/src/main/java/com/google/protobuf/MessageOrBuilder.java \ + java/src/main/java/com/google/protobuf/MessageReflection.java \ + java/src/main/java/com/google/protobuf/Parser.java \ java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java \ + java/src/main/java/com/google/protobuf/ProtocolStringList.java \ + java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java \ + java/src/main/java/com/google/protobuf/RopeByteString.java \ java/src/main/java/com/google/protobuf/RpcCallback.java \ java/src/main/java/com/google/protobuf/RpcChannel.java \ java/src/main/java/com/google/protobuf/RpcController.java \ java/src/main/java/com/google/protobuf/RpcUtil.java \ - java/src/main/java/com/google/protobuf/Service.java \ java/src/main/java/com/google/protobuf/ServiceException.java \ + java/src/main/java/com/google/protobuf/Service.java \ + java/src/main/java/com/google/protobuf/SingleFieldBuilder.java \ + java/src/main/java/com/google/protobuf/SmallSortedMap.java \ java/src/main/java/com/google/protobuf/TextFormat.java \ java/src/main/java/com/google/protobuf/UninitializedMessageException.java \ java/src/main/java/com/google/protobuf/UnknownFieldSet.java \ + java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java \ + java/src/main/java/com/google/protobuf/Utf8.java \ java/src/main/java/com/google/protobuf/WireFormat.java \ java/src/test/java/com/google/protobuf/AbstractMessageTest.java \ + java/src/test/java/com/google/protobuf/BoundedByteStringTest.java \ + java/src/test/java/com/google/protobuf/ByteStringTest.java \ + java/src/test/java/com/google/protobuf/CheckUtf8Test.java \ java/src/test/java/com/google/protobuf/CodedInputStreamTest.java \ java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java \ + java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java \ java/src/test/java/com/google/protobuf/DescriptorsTest.java \ java/src/test/java/com/google/protobuf/DynamicMessageTest.java \ + java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java \ java/src/test/java/com/google/protobuf/GeneratedMessageTest.java \ + java/src/test/java/com/google/protobuf/IsValidUtf8Test.java \ + java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java \ + java/src/test/java/com/google/protobuf/LazyFieldTest.java \ + java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java \ + java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java \ + java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java \ + java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java \ + java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java \ + java/src/test/java/com/google/protobuf/LiteralByteStringTest.java \ java/src/test/java/com/google/protobuf/LiteTest.java \ java/src/test/java/com/google/protobuf/MessageTest.java \ + java/src/test/java/com/google/protobuf/NestedBuildersTest.java \ + java/src/test/java/com/google/protobuf/ParserTest.java \ + java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java \ + java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java \ + java/src/test/java/com/google/protobuf/RopeByteStringTest.java \ java/src/test/java/com/google/protobuf/ServiceTest.java \ + java/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java \ + java/src/test/java/com/google/protobuf/SmallSortedMapTest.java \ + java/src/test/java/com/google/protobuf/TestBadIdentifiers.java \ java/src/test/java/com/google/protobuf/TestUtil.java \ java/src/test/java/com/google/protobuf/TextFormatTest.java \ java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java \ + java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \ java/src/test/java/com/google/protobuf/WireFormatTest.java \ + java/src/test/java/com/google/protobuf/lazy_fields_lite.proto \ + java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto \ java/src/test/java/com/google/protobuf/multiple_files_test.proto \ + java/src/test/java/com/google/protobuf/nested_builders_test.proto \ + java/src/test/java/com/google/protobuf/nested_extension_lite.proto \ + java/src/test/java/com/google/protobuf/nested_extension.proto \ + java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto \ + java/src/test/java/com/google/protobuf/non_nested_extension.proto \ + java/src/test/java/com/google/protobuf/outer_class_name_test.proto \ + java/src/test/java/com/google/protobuf/outer_class_name_test2.proto \ + java/src/test/java/com/google/protobuf/outer_class_name_test3.proto \ + java/src/test/java/com/google/protobuf/test_bad_identifiers.proto \ + java/src/test/java/com/google/protobuf/test_check_utf8.proto \ + java/src/test/java/com/google/protobuf/test_check_utf8_size.proto \ + java/src/test/java/com/google/protobuf/test_custom_options.proto \ java/pom.xml \ java/README.txt \ - python/google/protobuf/internal/generator_test.py \ + python/google/protobuf/internal/api_implementation.cc \ + python/google/protobuf/internal/api_implementation.py \ + python/google/protobuf/internal/api_implementation_default_test.py \ python/google/protobuf/internal/containers.py \ + python/google/protobuf/internal/cpp_message.py \ python/google/protobuf/internal/decoder.py \ + python/google/protobuf/internal/descriptor_database_test.py \ + python/google/protobuf/internal/descriptor_pool_test.py \ + python/google/protobuf/internal/descriptor_pool_test1.proto \ + python/google/protobuf/internal/descriptor_pool_test2.proto \ + python/google/protobuf/internal/descriptor_python_test.py \ python/google/protobuf/internal/descriptor_test.py \ python/google/protobuf/internal/encoder.py \ + python/google/protobuf/internal/enum_type_wrapper.py \ + python/google/protobuf/internal/factory_test1.proto \ + python/google/protobuf/internal/factory_test2.proto \ + python/google/protobuf/internal/generator_test.py \ + python/google/protobuf/internal/message_factory_python_test.py \ + python/google/protobuf/internal/message_factory_test.py \ python/google/protobuf/internal/message_listener.py \ + python/google/protobuf/internal/message_python_test.py \ python/google/protobuf/internal/message_test.py \ + python/google/protobuf/internal/missing_enum_values.proto \ python/google/protobuf/internal/more_extensions.proto \ + python/google/protobuf/internal/more_extensions_dynamic.proto \ python/google/protobuf/internal/more_messages.proto \ + python/google/protobuf/internal/python_message.py \ python/google/protobuf/internal/reflection_test.py \ python/google/protobuf/internal/service_reflection_test.py \ + python/google/protobuf/internal/symbol_database_test.py \ + python/google/protobuf/internal/test_bad_identifiers.proto \ python/google/protobuf/internal/test_util.py \ + python/google/protobuf/internal/text_encoding_test.py \ python/google/protobuf/internal/text_format_test.py \ python/google/protobuf/internal/type_checkers.py \ + python/google/protobuf/internal/unknown_fields_test.py \ python/google/protobuf/internal/wire_format.py \ python/google/protobuf/internal/wire_format_test.py \ python/google/protobuf/internal/__init__.py \ + python/google/protobuf/pyext/README \ + python/google/protobuf/pyext/cpp_message.py \ + python/google/protobuf/pyext/descriptor.h \ + python/google/protobuf/pyext/descriptor.cc \ + python/google/protobuf/pyext/descriptor_cpp2_test.py \ + python/google/protobuf/pyext/extension_dict.h \ + python/google/protobuf/pyext/extension_dict.cc \ + python/google/protobuf/pyext/message.h \ + python/google/protobuf/pyext/message.cc \ + python/google/protobuf/pyext/message_factory_cpp2_test.py \ + python/google/protobuf/pyext/proto2_api_test.proto \ + python/google/protobuf/pyext/python.proto \ + python/google/protobuf/pyext/python_protobuf.h \ + python/google/protobuf/pyext/reflection_cpp2_generated_test.py \ + python/google/protobuf/pyext/repeated_composite_container.h \ + python/google/protobuf/pyext/repeated_composite_container.cc \ + python/google/protobuf/pyext/repeated_scalar_container.h \ + python/google/protobuf/pyext/repeated_scalar_container.cc \ + python/google/protobuf/pyext/scoped_pyobject_ptr.h \ + python/google/protobuf/pyext/__init__.py \ python/google/protobuf/descriptor.py \ + python/google/protobuf/descriptor_database.py \ + python/google/protobuf/descriptor_pool.py \ python/google/protobuf/message.py \ + python/google/protobuf/message_factory.py \ python/google/protobuf/reflection.py \ python/google/protobuf/service.py \ python/google/protobuf/service_reflection.py \ + python/google/protobuf/symbol_database.py \ + python/google/protobuf/text_encoding.py \ python/google/protobuf/text_format.py \ python/google/protobuf/__init__.py \ python/google/__init__.py \ diff --git a/Makefile.in b/Makefile.in index d13f7c7..8309dd2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -159,6 +159,7 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -182,10 +183,13 @@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ @@ -213,6 +217,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ @@ -247,7 +252,6 @@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ @@ -282,9 +286,9 @@ pkgconfig_DATA = protobuf.pc protobuf-lite.pc EXTRA_DIST = \ autogen.sh \ generate_descriptor_proto.sh \ - README.txt \ + README.md \ INSTALL.txt \ - COPYING.txt \ + LICENSE \ CONTRIBUTORS.txt \ CHANGES.txt \ editors/README.txt \ @@ -313,13 +317,16 @@ EXTRA_DIST = \ examples/list_people.py \ java/src/main/java/com/google/protobuf/AbstractMessage.java \ java/src/main/java/com/google/protobuf/AbstractMessageLite.java \ + java/src/main/java/com/google/protobuf/AbstractParser.java \ java/src/main/java/com/google/protobuf/BlockingRpcChannel.java \ java/src/main/java/com/google/protobuf/BlockingService.java \ + java/src/main/java/com/google/protobuf/BoundedByteString.java \ java/src/main/java/com/google/protobuf/ByteString.java \ java/src/main/java/com/google/protobuf/CodedInputStream.java \ java/src/main/java/com/google/protobuf/CodedOutputStream.java \ java/src/main/java/com/google/protobuf/Descriptors.java \ java/src/main/java/com/google/protobuf/DynamicMessage.java \ + java/src/main/java/com/google/protobuf/Extension.java \ java/src/main/java/com/google/protobuf/ExtensionRegistry.java \ java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java \ java/src/main/java/com/google/protobuf/FieldSet.java \ @@ -327,57 +334,157 @@ EXTRA_DIST = \ java/src/main/java/com/google/protobuf/GeneratedMessageLite.java \ java/src/main/java/com/google/protobuf/Internal.java \ java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \ + java/src/main/java/com/google/protobuf/LazyField.java \ + java/src/main/java/com/google/protobuf/LazyFieldLite.java \ + java/src/main/java/com/google/protobuf/LazyStringArrayList.java \ + java/src/main/java/com/google/protobuf/LazyStringList.java \ + java/src/main/java/com/google/protobuf/LiteralByteString.java \ java/src/main/java/com/google/protobuf/Message.java \ java/src/main/java/com/google/protobuf/MessageLite.java \ + java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java \ + java/src/main/java/com/google/protobuf/MessageOrBuilder.java \ + java/src/main/java/com/google/protobuf/MessageReflection.java \ + java/src/main/java/com/google/protobuf/Parser.java \ java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java \ + java/src/main/java/com/google/protobuf/ProtocolStringList.java \ + java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java \ + java/src/main/java/com/google/protobuf/RopeByteString.java \ java/src/main/java/com/google/protobuf/RpcCallback.java \ java/src/main/java/com/google/protobuf/RpcChannel.java \ java/src/main/java/com/google/protobuf/RpcController.java \ java/src/main/java/com/google/protobuf/RpcUtil.java \ - java/src/main/java/com/google/protobuf/Service.java \ java/src/main/java/com/google/protobuf/ServiceException.java \ + java/src/main/java/com/google/protobuf/Service.java \ + java/src/main/java/com/google/protobuf/SingleFieldBuilder.java \ + java/src/main/java/com/google/protobuf/SmallSortedMap.java \ java/src/main/java/com/google/protobuf/TextFormat.java \ java/src/main/java/com/google/protobuf/UninitializedMessageException.java \ java/src/main/java/com/google/protobuf/UnknownFieldSet.java \ + java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java \ + java/src/main/java/com/google/protobuf/Utf8.java \ java/src/main/java/com/google/protobuf/WireFormat.java \ java/src/test/java/com/google/protobuf/AbstractMessageTest.java \ + java/src/test/java/com/google/protobuf/BoundedByteStringTest.java \ + java/src/test/java/com/google/protobuf/ByteStringTest.java \ + java/src/test/java/com/google/protobuf/CheckUtf8Test.java \ java/src/test/java/com/google/protobuf/CodedInputStreamTest.java \ java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java \ + java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java \ java/src/test/java/com/google/protobuf/DescriptorsTest.java \ java/src/test/java/com/google/protobuf/DynamicMessageTest.java \ + java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java \ java/src/test/java/com/google/protobuf/GeneratedMessageTest.java \ + java/src/test/java/com/google/protobuf/IsValidUtf8Test.java \ + java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java \ + java/src/test/java/com/google/protobuf/LazyFieldTest.java \ + java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java \ + java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java \ + java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java \ + java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java \ + java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java \ + java/src/test/java/com/google/protobuf/LiteralByteStringTest.java \ java/src/test/java/com/google/protobuf/LiteTest.java \ java/src/test/java/com/google/protobuf/MessageTest.java \ + java/src/test/java/com/google/protobuf/NestedBuildersTest.java \ + java/src/test/java/com/google/protobuf/ParserTest.java \ + java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java \ + java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java \ + java/src/test/java/com/google/protobuf/RopeByteStringTest.java \ java/src/test/java/com/google/protobuf/ServiceTest.java \ + java/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java \ + java/src/test/java/com/google/protobuf/SmallSortedMapTest.java \ + java/src/test/java/com/google/protobuf/TestBadIdentifiers.java \ java/src/test/java/com/google/protobuf/TestUtil.java \ java/src/test/java/com/google/protobuf/TextFormatTest.java \ java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java \ + java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \ java/src/test/java/com/google/protobuf/WireFormatTest.java \ + java/src/test/java/com/google/protobuf/lazy_fields_lite.proto \ + java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto \ java/src/test/java/com/google/protobuf/multiple_files_test.proto \ + java/src/test/java/com/google/protobuf/nested_builders_test.proto \ + java/src/test/java/com/google/protobuf/nested_extension_lite.proto \ + java/src/test/java/com/google/protobuf/nested_extension.proto \ + java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto \ + java/src/test/java/com/google/protobuf/non_nested_extension.proto \ + java/src/test/java/com/google/protobuf/outer_class_name_test.proto \ + java/src/test/java/com/google/protobuf/outer_class_name_test2.proto \ + java/src/test/java/com/google/protobuf/outer_class_name_test3.proto \ + java/src/test/java/com/google/protobuf/test_bad_identifiers.proto \ + java/src/test/java/com/google/protobuf/test_check_utf8.proto \ + java/src/test/java/com/google/protobuf/test_check_utf8_size.proto \ + java/src/test/java/com/google/protobuf/test_custom_options.proto \ java/pom.xml \ java/README.txt \ - python/google/protobuf/internal/generator_test.py \ + python/google/protobuf/internal/api_implementation.cc \ + python/google/protobuf/internal/api_implementation.py \ + python/google/protobuf/internal/api_implementation_default_test.py \ python/google/protobuf/internal/containers.py \ + python/google/protobuf/internal/cpp_message.py \ python/google/protobuf/internal/decoder.py \ + python/google/protobuf/internal/descriptor_database_test.py \ + python/google/protobuf/internal/descriptor_pool_test.py \ + python/google/protobuf/internal/descriptor_pool_test1.proto \ + python/google/protobuf/internal/descriptor_pool_test2.proto \ + python/google/protobuf/internal/descriptor_python_test.py \ python/google/protobuf/internal/descriptor_test.py \ python/google/protobuf/internal/encoder.py \ + python/google/protobuf/internal/enum_type_wrapper.py \ + python/google/protobuf/internal/factory_test1.proto \ + python/google/protobuf/internal/factory_test2.proto \ + python/google/protobuf/internal/generator_test.py \ + python/google/protobuf/internal/message_factory_python_test.py \ + python/google/protobuf/internal/message_factory_test.py \ python/google/protobuf/internal/message_listener.py \ + python/google/protobuf/internal/message_python_test.py \ python/google/protobuf/internal/message_test.py \ + python/google/protobuf/internal/missing_enum_values.proto \ python/google/protobuf/internal/more_extensions.proto \ + python/google/protobuf/internal/more_extensions_dynamic.proto \ python/google/protobuf/internal/more_messages.proto \ + python/google/protobuf/internal/python_message.py \ python/google/protobuf/internal/reflection_test.py \ python/google/protobuf/internal/service_reflection_test.py \ + python/google/protobuf/internal/symbol_database_test.py \ + python/google/protobuf/internal/test_bad_identifiers.proto \ python/google/protobuf/internal/test_util.py \ + python/google/protobuf/internal/text_encoding_test.py \ python/google/protobuf/internal/text_format_test.py \ python/google/protobuf/internal/type_checkers.py \ + python/google/protobuf/internal/unknown_fields_test.py \ python/google/protobuf/internal/wire_format.py \ python/google/protobuf/internal/wire_format_test.py \ python/google/protobuf/internal/__init__.py \ + python/google/protobuf/pyext/README \ + python/google/protobuf/pyext/cpp_message.py \ + python/google/protobuf/pyext/descriptor.h \ + python/google/protobuf/pyext/descriptor.cc \ + python/google/protobuf/pyext/descriptor_cpp2_test.py \ + python/google/protobuf/pyext/extension_dict.h \ + python/google/protobuf/pyext/extension_dict.cc \ + python/google/protobuf/pyext/message.h \ + python/google/protobuf/pyext/message.cc \ + python/google/protobuf/pyext/message_factory_cpp2_test.py \ + python/google/protobuf/pyext/proto2_api_test.proto \ + python/google/protobuf/pyext/python.proto \ + python/google/protobuf/pyext/python_protobuf.h \ + python/google/protobuf/pyext/reflection_cpp2_generated_test.py \ + python/google/protobuf/pyext/repeated_composite_container.h \ + python/google/protobuf/pyext/repeated_composite_container.cc \ + python/google/protobuf/pyext/repeated_scalar_container.h \ + python/google/protobuf/pyext/repeated_scalar_container.cc \ + python/google/protobuf/pyext/scoped_pyobject_ptr.h \ + python/google/protobuf/pyext/__init__.py \ python/google/protobuf/descriptor.py \ + python/google/protobuf/descriptor_database.py \ + python/google/protobuf/descriptor_pool.py \ python/google/protobuf/message.py \ + python/google/protobuf/message_factory.py \ python/google/protobuf/reflection.py \ python/google/protobuf/service.py \ python/google/protobuf/service_reflection.py \ + python/google/protobuf/symbol_database.py \ + python/google/protobuf/text_encoding.py \ python/google/protobuf/text_format.py \ python/google/protobuf/__init__.py \ python/google/__init__.py \ @@ -414,7 +521,7 @@ all: config.h .SUFFIXES: am--refresh: Makefile @: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -441,9 +548,9 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck -$(top_srcdir)/configure: $(am__configure_deps) +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) -$(ACLOCAL_M4): $(am__aclocal_m4_deps) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): @@ -454,7 +561,7 @@ config.h: stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h -$(srcdir)/config.h.in: $(am__configure_deps) +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ diff --git a/README.md b/README.md new file mode 100644 index 0000000..5fbb344 --- /dev/null +++ b/README.md @@ -0,0 +1,167 @@ +Protocol Buffers - Google's data interchange format +=================================================== + +Copyright 2008 Google Inc. + +https://developers.google.com/protocol-buffers/ + +C++ Installation - Unix +----------------------- + +If you get the source from github, you need to generate the configure script +first: + + $ ./autogen.sh + +This will download gtest source (which is used for C++ Protocol Buffer +unit-tests) to the current directory and run automake, autoconf, etc. +to generate the configure script and various template makefiles. + +You can skip this step if you are using a release package (which already +contains gtest and the configure script). + +To build and install the C++ Protocol Buffer runtime and the Protocol +Buffer compiler (protoc) execute the following: + + $ ./configure + $ make + $ make check + $ make install + +If "make check" fails, you can still install, but it is likely that +some features of this library will not work correctly on your system. +Proceed at your own risk. + +"make install" may require superuser privileges. + +For advanced usage information on configure and make, see INSTALL.txt. + +**Hint on install location** + + By default, the package will be installed to /usr/local. However, + on many platforms, /usr/local/lib is not part of LD_LIBRARY_PATH. + You can add it, but it may be easier to just install to /usr + instead. To do this, invoke configure as follows: + + ./configure --prefix=/usr + + If you already built the package with a different prefix, make sure + to run "make clean" before building again. + +**Compiling dependent packages** + + To compile a package that uses Protocol Buffers, you need to pass + various flags to your compiler and linker. As of version 2.2.0, + Protocol Buffers integrates with pkg-config to manage this. If you + have pkg-config installed, then you can invoke it to get a list of + flags like so: + + pkg-config --cflags protobuf # print compiler flags + pkg-config --libs protobuf # print linker flags + pkg-config --cflags --libs protobuf # print both + + For example: + + c++ my_program.cc my_proto.pb.cc `pkg-config --cflags --libs protobuf` + + Note that packages written prior to the 2.2.0 release of Protocol + Buffers may not yet integrate with pkg-config to get flags, and may + not pass the correct set of flags to correctly link against + libprotobuf. If the package in question uses autoconf, you can + often fix the problem by invoking its configure script like: + + configure CXXFLAGS="$(pkg-config --cflags protobuf)" \ + LIBS="$(pkg-config --libs protobuf)" + + This will force it to use the correct flags. + + If you are writing an autoconf-based package that uses Protocol + Buffers, you should probably use the PKG_CHECK_MODULES macro in your + configure script like: + + PKG_CHECK_MODULES([protobuf], [protobuf]) + + See the pkg-config man page for more info. + + If you only want protobuf-lite, substitute "protobuf-lite" in place + of "protobuf" in these examples. + +**Note for cross-compiling** + + The makefiles normally invoke the protoc executable that they just + built in order to build tests. When cross-compiling, the protoc + executable may not be executable on the host machine. In this case, + you must build a copy of protoc for the host machine first, then use + the --with-protoc option to tell configure to use it instead. For + example: + + ./configure --with-protoc=protoc + + This will use the installed protoc (found in your $PATH) instead of + trying to execute the one built during the build process. You can + also use an executable that hasn't been installed. For example, if + you built the protobuf package for your host machine in ../host, + you might do: + + ./configure --with-protoc=../host/src/protoc + + Either way, you must make sure that the protoc executable you use + has the same version as the protobuf source code you are trying to + use it with. + +**Note for Solaris users** + + Solaris 10 x86 has a bug that will make linking fail, complaining + about libstdc++.la being invalid. We have included a work-around + in this package. To use the work-around, run configure as follows: + + ./configure LDFLAGS=-L$PWD/src/solaris + + See src/solaris/libstdc++.la for more info on this bug. + +**Note for HP C++ Tru64 users** + + To compile invoke configure as follows: + + ./configure CXXFLAGS="-O -std ansi -ieee -D__USE_STD_IOSTREAM" + + Also, you will need to use gmake instead of make. + +C++ Installation - Windows +-------------------------- + +If you are using Microsoft Visual C++, see vsprojects/readme.txt. + +If you are using Cygwin or MinGW, follow the Unix installation +instructions, above. + +Binary Compatibility Warning +---------------------------- + +Due to the nature of C++, it is unlikely that any two versions of the +Protocol Buffers C++ runtime libraries will have compatible ABIs. +That is, if you linked an executable against an older version of +libprotobuf, it is unlikely to work with a newer version without +re-compiling. This problem, when it occurs, will normally be detected +immediately on startup of your app. Still, you may want to consider +using static linkage. You can configure this package to install +static libraries only using: + + ./configure --disable-shared + +Java and Python Installation +---------------------------- + +The Java and Python runtime libraries for Protocol Buffers are located +in the java and python directories. See the README file in each +directory for more information on how to compile and install them. +Note that both of them require you to first install the Protocol +Buffer compiler (protoc), which is part of the C++ package. + +Usage +----- + +The complete documentation for Protocol Buffers is available via the +web at: + + https://developers.google.com/protocol-buffers/ diff --git a/README.txt b/README.txt deleted file mode 100644 index a8f6604..0000000 --- a/README.txt +++ /dev/null @@ -1,152 +0,0 @@ -Protocol Buffers - Google's data interchange format -Copyright 2008 Google Inc. -http://code.google.com/apis/protocolbuffers/ - -C++ Installation - Unix -======================= - -To build and install the C++ Protocol Buffer runtime and the Protocol -Buffer compiler (protoc) execute the following: - - $ ./configure - $ make - $ make check - $ make install - -If "make check" fails, you can still install, but it is likely that -some features of this library will not work correctly on your system. -Proceed at your own risk. - -"make install" may require superuser privileges. - -For advanced usage information on configure and make, see INSTALL.txt. - -** Hint on install location ** - - By default, the package will be installed to /usr/local. However, - on many platforms, /usr/local/lib is not part of LD_LIBRARY_PATH. - You can add it, but it may be easier to just install to /usr - instead. To do this, invoke configure as follows: - - ./configure --prefix=/usr - - If you already built the package with a different prefix, make sure - to run "make clean" before building again. - -** Compiling dependent packages ** - - To compile a package that uses Protocol Buffers, you need to pass - various flags to your compiler and linker. As of version 2.2.0, - Protocol Buffers integrates with pkg-config to manage this. If you - have pkg-config installed, then you can invoke it to get a list of - flags like so: - - pkg-config --cflags protobuf # print compiler flags - pkg-config --libs protobuf # print linker flags - pkg-config --cflags --libs protobuf # print both - - For example: - - c++ my_program.cc my_proto.pb.cc `pkg-config --cflags --libs protobuf` - - Note that packages written prior to the 2.2.0 release of Protocol - Buffers may not yet integrate with pkg-config to get flags, and may - not pass the correct set of flags to correctly link against - libprotobuf. If the package in question uses autoconf, you can - often fix the problem by invoking its configure script like: - - configure CXXFLAGS="$(pkg-config --cflags protobuf)" \ - LIBS="$(pkg-config --libs protobuf)" - - This will force it to use the correct flags. - - If you are writing an autoconf-based package that uses Protocol - Buffers, you should probably use the PKG_CHECK_MODULES macro in your - configure script like: - - PKG_CHECK_MODULES([protobuf], [protobuf]) - - See the pkg-config man page for more info. - - If you only want protobuf-lite, substitute "protobuf-lite" in place - of "protobuf" in these examples. - -** Note for cross-compiling ** - - The makefiles normally invoke the protoc executable that they just - built in order to build tests. When cross-compiling, the protoc - executable may not be executable on the host machine. In this case, - you must build a copy of protoc for the host machine first, then use - the --with-protoc option to tell configure to use it instead. For - example: - - ./configure --with-protoc=protoc - - This will use the installed protoc (found in your $PATH) instead of - trying to execute the one built during the build process. You can - also use an executable that hasn't been installed. For example, if - you built the protobuf package for your host machine in ../host, - you might do: - - ./configure --with-protoc=../host/src/protoc - - Either way, you must make sure that the protoc executable you use - has the same version as the protobuf source code you are trying to - use it with. - -** Note for Solaris users ** - - Solaris 10 x86 has a bug that will make linking fail, complaining - about libstdc++.la being invalid. We have included a work-around - in this package. To use the work-around, run configure as follows: - - ./configure LDFLAGS=-L$PWD/src/solaris - - See src/solaris/libstdc++.la for more info on this bug. - -** Note for HP C++ Tru64 users ** - - To compile invoke configure as follows: - - ./configure CXXFLAGS="-O -std ansi -ieee -D__USE_STD_IOSTREAM" - - Also, you will need to use gmake instead of make. - -C++ Installation - Windows -========================== - -If you are using Micosoft Visual C++, see vsprojects/readme.txt. - -If you are using Cygwin or MinGW, follow the Unix installation -instructions, above. - -Binary Compatibility Warning -============================ - -Due to the nature of C++, it is unlikely that any two versions of the -Protocol Buffers C++ runtime libraries will have compatible ABIs. -That is, if you linked an executable against an older version of -libprotobuf, it is unlikely to work with a newer version without -re-compiling. This problem, when it occurs, will normally be detected -immediately on startup of your app. Still, you may want to consider -using static linkage. You can configure this package to install -static libraries only using: - - ./configure --disable-shared - -Java and Python Installation -============================ - -The Java and Python runtime libraries for Protocol Buffers are located -in the java and python directories. See the README file in each -directory for more information on how to compile and install them. -Note that both of them require you to first install the Protocol -Buffer compiler (protoc), which is part of the C++ package. - -Usage -===== - -The complete documentation for Protocol Buffers is available via the -web at: - - http://code.google.com/apis/protocolbuffers/ diff --git a/aclocal.m4 b/aclocal.m4 index 375941e..5081ad9 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -600,6 +600,46 @@ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008, +# 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless `enable' is passed literally. +# For symmetry, `disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], +[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) + # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. diff --git a/autogen.sh b/autogen.sh index 04d65b1..c3e026d 100755 --- a/autogen.sh +++ b/autogen.sh @@ -18,9 +18,9 @@ fi # Check that gtest is present. Usually it is already there since the # directory is set up as an SVN external. if test ! -e gtest; then - echo "Google Test not present. Fetching gtest-1.3.0 from the web..." - curl http://googletest.googlecode.com/files/gtest-1.3.0.tar.bz2 | tar jx - mv gtest-1.3.0 gtest + echo "Google Test not present. Fetching gtest-1.5.0 from the web..." + curl http://googletest.googlecode.com/files/gtest-1.5.0.tar.bz2 | tar jx + mv gtest-1.5.0 gtest fi set -ex diff --git a/benchmarks/ProtoBench.java b/benchmarks/ProtoBench.java new file mode 100644 index 0000000..6717ffa --- /dev/null +++ b/benchmarks/ProtoBench.java @@ -0,0 +1,203 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2009 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protocolbuffers; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.lang.reflect.Method; + +import com.google.protobuf.ByteString; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; +import com.google.protobuf.Message; + +public class ProtoBench { + + private static final long MIN_SAMPLE_TIME_MS = 2 * 1000; + private static final long TARGET_TIME_MS = 30 * 1000; + + private ProtoBench() { + // Prevent instantiation + } + + public static void main(String[] args) { + if (args.length < 2 || (args.length % 2) != 0) { + System.err.println("Usage: ProtoBench "); + System.err.println("The descriptor type name is the fully-qualified message name,"); + System.err.println("e.g. com.google.protocolbuffers.benchmark.Message1"); + System.err.println("(You can specify multiple pairs of descriptor type name and input data.)"); + System.exit(1); + } + boolean success = true; + for (int i = 0; i < args.length; i += 2) { + success &= runTest(args[i], args[i + 1]); + } + System.exit(success ? 0 : 1); + } + + /** + * Runs a single test. Error messages are displayed to stderr, and the return value + * indicates general success/failure. + */ + public static boolean runTest(String type, String file) { + System.out.println("Benchmarking " + type + " with file " + file); + final Message defaultMessage; + try { + Class clazz = Class.forName(type); + Method method = clazz.getDeclaredMethod("getDefaultInstance"); + defaultMessage = (Message) method.invoke(null); + } catch (Exception e) { + // We want to do the same thing with all exceptions. Not generally nice, + // but this is slightly different. + System.err.println("Unable to get default message for " + type); + return false; + } + + try { + final byte[] inputData = readAllBytes(file); + final ByteArrayInputStream inputStream = new ByteArrayInputStream(inputData); + final ByteString inputString = ByteString.copyFrom(inputData); + final Message sampleMessage = defaultMessage.newBuilderForType().mergeFrom(inputString).build(); + FileOutputStream devNullTemp = null; + CodedOutputStream reuseDevNullTemp = null; + try { + devNullTemp = new FileOutputStream("/dev/null"); + reuseDevNullTemp = CodedOutputStream.newInstance(devNullTemp); + } catch (FileNotFoundException e) { + // ignore: this is probably Windows, where /dev/null does not exist + } + final FileOutputStream devNull = devNullTemp; + final CodedOutputStream reuseDevNull = reuseDevNullTemp; + benchmark("Serialize to byte string", inputData.length, new Action() { + public void execute() { sampleMessage.toByteString(); } + }); + benchmark("Serialize to byte array", inputData.length, new Action() { + public void execute() { sampleMessage.toByteArray(); } + }); + benchmark("Serialize to memory stream", inputData.length, new Action() { + public void execute() throws IOException { + sampleMessage.writeTo(new ByteArrayOutputStream()); + } + }); + if (devNull != null) { + benchmark("Serialize to /dev/null with FileOutputStream", inputData.length, new Action() { + public void execute() throws IOException { + sampleMessage.writeTo(devNull); + } + }); + benchmark("Serialize to /dev/null reusing FileOutputStream", inputData.length, new Action() { + public void execute() throws IOException { + sampleMessage.writeTo(reuseDevNull); + reuseDevNull.flush(); // force the write to the OutputStream + } + }); + } + benchmark("Deserialize from byte string", inputData.length, new Action() { + public void execute() throws IOException { + defaultMessage.newBuilderForType().mergeFrom(inputString).build(); + } + }); + benchmark("Deserialize from byte array", inputData.length, new Action() { + public void execute() throws IOException { + defaultMessage.newBuilderForType() + .mergeFrom(CodedInputStream.newInstance(inputData)).build(); + } + }); + benchmark("Deserialize from memory stream", inputData.length, new Action() { + public void execute() throws IOException { + defaultMessage.newBuilderForType() + .mergeFrom(CodedInputStream.newInstance(inputStream)).build(); + inputStream.reset(); + } + }); + System.out.println(); + return true; + } catch (Exception e) { + System.err.println("Error: " + e.getMessage()); + System.err.println("Detailed exception information:"); + e.printStackTrace(System.err); + return false; + } + } + + private static void benchmark(String name, long dataSize, Action action) throws IOException { + // Make sure it's JITted "reasonably" hard before running the first progress test + for (int i=0; i < 100; i++) { + action.execute(); + } + + // Run it progressively more times until we've got a reasonable sample + int iterations = 1; + long elapsed = timeAction(action, iterations); + while (elapsed < MIN_SAMPLE_TIME_MS) { + iterations *= 2; + elapsed = timeAction(action, iterations); + } + + // Upscale the sample to the target time. Do this in floating point arithmetic + // to avoid overflow issues. + iterations = (int) ((TARGET_TIME_MS / (double) elapsed) * iterations); + elapsed = timeAction(action, iterations); + System.out.println(name + ": " + iterations + " iterations in " + + (elapsed/1000f) + "s; " + + (iterations * dataSize) / (elapsed * 1024 * 1024 / 1000f) + + "MB/s"); + } + + private static long timeAction(Action action, int iterations) throws IOException { + System.gc(); + long start = System.currentTimeMillis(); + for (int i = 0; i < iterations; i++) { + action.execute(); + } + long end = System.currentTimeMillis(); + return end - start; + } + + private static byte[] readAllBytes(String filename) throws IOException { + RandomAccessFile file = new RandomAccessFile(new File(filename), "r"); + byte[] content = new byte[(int) file.length()]; + file.readFully(content); + return content; + } + + /** + * Interface used to capture a single action to benchmark. + */ + interface Action { + void execute() throws IOException; + } +} diff --git a/benchmarks/google_message1.dat b/benchmarks/google_message1.dat new file mode 100644 index 0000000..bc0f064 Binary files /dev/null and b/benchmarks/google_message1.dat differ diff --git a/benchmarks/google_message2.dat b/benchmarks/google_message2.dat new file mode 100644 index 0000000..06c0944 Binary files /dev/null and b/benchmarks/google_message2.dat differ diff --git a/benchmarks/google_size.proto b/benchmarks/google_size.proto new file mode 100644 index 0000000..3e6fbdb --- /dev/null +++ b/benchmarks/google_size.proto @@ -0,0 +1,136 @@ +package benchmarks; + +option java_outer_classname = "GoogleSize"; +option optimize_for = CODE_SIZE; + +message SizeMessage1 { + required string field1 = 1; + optional string field9 = 9; + optional string field18 = 18; + optional bool field80 = 80 [default=false]; + optional bool field81 = 81 [default=true]; + required int32 field2 = 2; + required int32 field3 = 3; + optional int32 field280 = 280; + optional int32 field6 = 6 [default=0]; + optional int64 field22 = 22; + optional string field4 = 4; + repeated fixed64 field5 = 5; + optional bool field59 = 59 [default=false]; + optional string field7 = 7; + optional int32 field16 = 16; + optional int32 field130 = 130 [default=0]; + optional bool field12 = 12 [default=true]; + optional bool field17 = 17 [default=true]; + optional bool field13 = 13 [default=true]; + optional bool field14 = 14 [default=true]; + optional int32 field104 = 104 [default=0]; + optional int32 field100 = 100 [default=0]; + optional int32 field101 = 101 [default=0]; + optional string field102 = 102; + optional string field103 = 103; + optional int32 field29 = 29 [default=0]; + optional bool field30 = 30 [default=false]; + optional int32 field60 = 60 [default=-1]; + optional int32 field271 = 271 [default=-1]; + optional int32 field272 = 272 [default=-1]; + optional int32 field150 = 150; + optional int32 field23 = 23 [default=0]; + optional bool field24 = 24 [default=false]; + optional int32 field25 = 25 [default=0]; + optional SizeMessage1SubMessage field15 = 15; + optional bool field78 = 78; + optional int32 field67 = 67 [default=0]; + optional int32 field68 = 68; + optional int32 field128 = 128 [default=0]; + optional string field129 = 129 [default="xxxxxxxxxxxxxxxxxxxxx"]; + optional int32 field131 = 131 [default=0]; +} + +message SizeMessage1SubMessage { + optional int32 field1 = 1 [default=0]; + optional int32 field2 = 2 [default=0]; + optional int32 field3 = 3 [default=0]; + optional string field15 = 15; + optional bool field12 = 12 [default=true]; + optional int64 field13 = 13; + optional int64 field14 = 14; + optional int32 field16 = 16; + optional int32 field19 = 19 [default=2]; + optional bool field20 = 20 [default=true]; + optional bool field28 = 28 [default=true]; + optional fixed64 field21 = 21; + optional int32 field22 = 22; + optional bool field23 = 23 [ default=false ]; + optional bool field206 = 206 [default=false]; + optional fixed32 field203 = 203; + optional int32 field204 = 204; + optional string field205 = 205; + optional uint64 field207 = 207; + optional uint64 field300 = 300; +} + +message SizeMessage2 { + optional string field1 = 1; + optional int64 field3 = 3; + optional int64 field4 = 4; + optional int64 field30 = 30; + optional bool field75 = 75 [default=false]; + optional string field6 = 6; + optional bytes field2 = 2; + optional int32 field21 = 21 [default=0]; + optional int32 field71 = 71; + optional float field25 = 25; + optional int32 field109 = 109 [default=0]; + optional int32 field210 = 210 [default=0]; + optional int32 field211 = 211 [default=0]; + optional int32 field212 = 212 [default=0]; + optional int32 field213 = 213 [default=0]; + optional int32 field216 = 216 [default=0]; + optional int32 field217 = 217 [default=0]; + optional int32 field218 = 218 [default=0]; + optional int32 field220 = 220 [default=0]; + optional int32 field221 = 221 [default=0]; + optional float field222 = 222 [default=0.0]; + optional int32 field63 = 63; + + repeated group Group1 = 10 { + required float field11 = 11; + optional float field26 = 26; + optional string field12 = 12; + optional string field13 = 13; + repeated string field14 = 14; + required uint64 field15 = 15; + optional int32 field5 = 5; + optional string field27 = 27; + optional int32 field28 = 28; + optional string field29 = 29; + optional string field16 = 16; + repeated string field22 = 22; + repeated int32 field73 = 73; + optional int32 field20 = 20 [default=0]; + optional string field24 = 24; + optional SizeMessage2GroupedMessage field31 = 31; + } + repeated string field128 = 128; + optional int64 field131 = 131; + repeated string field127 = 127; + optional int32 field129 = 129; + repeated int64 field130 = 130; + optional bool field205 = 205 [default=false]; + optional bool field206 = 206 [default=false]; +} + +message SizeMessage2GroupedMessage { + optional float field1 = 1; + optional float field2 = 2; + optional float field3 = 3 [default=0.0]; + optional bool field4 = 4; + optional bool field5 = 5; + optional bool field6 = 6 [default=true]; + optional bool field7 = 7 [default=false]; + optional float field8 = 8; + optional bool field9 = 9; + optional float field10 = 10; + optional int64 field11 = 11; +} diff --git a/benchmarks/google_speed.proto b/benchmarks/google_speed.proto new file mode 100644 index 0000000..d6cd032 --- /dev/null +++ b/benchmarks/google_speed.proto @@ -0,0 +1,136 @@ +package benchmarks; + +option java_outer_classname = "GoogleSpeed"; +option optimize_for = SPEED; + +message SpeedMessage1 { + required string field1 = 1; + optional string field9 = 9; + optional string field18 = 18; + optional bool field80 = 80 [default=false]; + optional bool field81 = 81 [default=true]; + required int32 field2 = 2; + required int32 field3 = 3; + optional int32 field280 = 280; + optional int32 field6 = 6 [default=0]; + optional int64 field22 = 22; + optional string field4 = 4; + repeated fixed64 field5 = 5; + optional bool field59 = 59 [default=false]; + optional string field7 = 7; + optional int32 field16 = 16; + optional int32 field130 = 130 [default=0]; + optional bool field12 = 12 [default=true]; + optional bool field17 = 17 [default=true]; + optional bool field13 = 13 [default=true]; + optional bool field14 = 14 [default=true]; + optional int32 field104 = 104 [default=0]; + optional int32 field100 = 100 [default=0]; + optional int32 field101 = 101 [default=0]; + optional string field102 = 102; + optional string field103 = 103; + optional int32 field29 = 29 [default=0]; + optional bool field30 = 30 [default=false]; + optional int32 field60 = 60 [default=-1]; + optional int32 field271 = 271 [default=-1]; + optional int32 field272 = 272 [default=-1]; + optional int32 field150 = 150; + optional int32 field23 = 23 [default=0]; + optional bool field24 = 24 [default=false]; + optional int32 field25 = 25 [default=0]; + optional SpeedMessage1SubMessage field15 = 15; + optional bool field78 = 78; + optional int32 field67 = 67 [default=0]; + optional int32 field68 = 68; + optional int32 field128 = 128 [default=0]; + optional string field129 = 129 [default="xxxxxxxxxxxxxxxxxxxxx"]; + optional int32 field131 = 131 [default=0]; +} + +message SpeedMessage1SubMessage { + optional int32 field1 = 1 [default=0]; + optional int32 field2 = 2 [default=0]; + optional int32 field3 = 3 [default=0]; + optional string field15 = 15; + optional bool field12 = 12 [default=true]; + optional int64 field13 = 13; + optional int64 field14 = 14; + optional int32 field16 = 16; + optional int32 field19 = 19 [default=2]; + optional bool field20 = 20 [default=true]; + optional bool field28 = 28 [default=true]; + optional fixed64 field21 = 21; + optional int32 field22 = 22; + optional bool field23 = 23 [ default=false ]; + optional bool field206 = 206 [default=false]; + optional fixed32 field203 = 203; + optional int32 field204 = 204; + optional string field205 = 205; + optional uint64 field207 = 207; + optional uint64 field300 = 300; +} + +message SpeedMessage2 { + optional string field1 = 1; + optional int64 field3 = 3; + optional int64 field4 = 4; + optional int64 field30 = 30; + optional bool field75 = 75 [default=false]; + optional string field6 = 6; + optional bytes field2 = 2; + optional int32 field21 = 21 [default=0]; + optional int32 field71 = 71; + optional float field25 = 25; + optional int32 field109 = 109 [default=0]; + optional int32 field210 = 210 [default=0]; + optional int32 field211 = 211 [default=0]; + optional int32 field212 = 212 [default=0]; + optional int32 field213 = 213 [default=0]; + optional int32 field216 = 216 [default=0]; + optional int32 field217 = 217 [default=0]; + optional int32 field218 = 218 [default=0]; + optional int32 field220 = 220 [default=0]; + optional int32 field221 = 221 [default=0]; + optional float field222 = 222 [default=0.0]; + optional int32 field63 = 63; + + repeated group Group1 = 10 { + required float field11 = 11; + optional float field26 = 26; + optional string field12 = 12; + optional string field13 = 13; + repeated string field14 = 14; + required uint64 field15 = 15; + optional int32 field5 = 5; + optional string field27 = 27; + optional int32 field28 = 28; + optional string field29 = 29; + optional string field16 = 16; + repeated string field22 = 22; + repeated int32 field73 = 73; + optional int32 field20 = 20 [default=0]; + optional string field24 = 24; + optional SpeedMessage2GroupedMessage field31 = 31; + } + repeated string field128 = 128; + optional int64 field131 = 131; + repeated string field127 = 127; + optional int32 field129 = 129; + repeated int64 field130 = 130; + optional bool field205 = 205 [default=false]; + optional bool field206 = 206 [default=false]; +} + +message SpeedMessage2GroupedMessage { + optional float field1 = 1; + optional float field2 = 2; + optional float field3 = 3 [default=0.0]; + optional bool field4 = 4; + optional bool field5 = 5; + optional bool field6 = 6 [default=true]; + optional bool field7 = 7 [default=false]; + optional float field8 = 8; + optional bool field9 = 9; + optional float field10 = 10; + optional int64 field11 = 11; +} diff --git a/benchmarks/readme.txt b/benchmarks/readme.txt new file mode 100644 index 0000000..2c836d0 --- /dev/null +++ b/benchmarks/readme.txt @@ -0,0 +1,50 @@ +Contents +-------- + +This folder contains three kinds of file: + +- Code, such as ProtoBench.java, to build the benchmarking framework. +- Protocol buffer definitions (.proto files) +- Sample data files + +If we end up with a lot of different benchmarks it may be worth +separating these out info different directories, but while there are +so few they might as well all be together. + +Running a benchmark (Java) +-------------------------- + +1) Build protoc and the Java protocol buffer library. The examples + below assume a jar file (protobuf.jar) has been built and copied + into this directory. + +2) Build ProtoBench: + $ javac -d tmp -cp protobuf.jar ProtoBench.java + +3) Generate code for the relevant benchmark protocol buffer, e.g. + $ protoc --java_out=tmp google_size.proto google_speed.proto + +4) Build the generated code, e.g. + $ cd tmp + $ javac -d . -cp ../protobuf.jar benchmarks/*.java + +5) Run the test. Arguments are given in pairs - the first argument + is the descriptor type; the second is the filename. For example: + $ java -cp .;../protobuf.jar com.google.protocolbuffers.ProtoBench + benchmarks.GoogleSize$SizeMessage1 ../google_message1.dat + benchmarks.GoogleSpeed$SpeedMessage1 ../google_message1.dat + benchmarks.GoogleSize$SizeMessage2 ../google_message2.dat + benchmarks.GoogleSpeed$SpeedMessage2 ../google_message2.dat + +6) Wait! Each test runs for around 30 seconds, and there are 6 tests + per class/data combination. The above command would therefore take + about 12 minutes to run. + + +Benchmarks available +-------------------- + +From Google: +google_size.proto and google_speed.proto, messages +google_message1.dat and google_message2.dat. The proto files are +equivalent, but optimized differently. diff --git a/build.gradle b/build.gradle index 95c9b1d..4684592 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ jar { from sourceSets.nano.output, sourceSets.micro.output baseName "libprotobuf" appendix "java" - version "2.3" + version "2.6" classifier "micronano" } @@ -64,7 +64,7 @@ task nanoJar(type: Jar) { dependsOn nanoClasses baseName "libprotobuf" appendix "java" - version "2.3" + version "2.6" classifier "nano" } @@ -73,7 +73,7 @@ task microJar(type: Jar) { dependsOn microClasses baseName "libprotobuf" appendix "java" - version "2.3" + version "2.6" classifier "micro" } diff --git a/config.guess b/config.guess index 278f9e9..d622a44 100755 --- a/config.guess +++ b/config.guess @@ -1,10 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. -timestamp='2007-07-22' +timestamp='2012-02-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -17,9 +17,7 @@ timestamp='2007-07-22' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -27,16 +25,16 @@ timestamp='2007-07-22' # the same distribution terms that you use for the rest of that program. -# Originally written by Per Bothner . -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` @@ -56,7 +54,8 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -144,7 +143,7 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward @@ -170,7 +169,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null + | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? @@ -180,7 +179,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in fi ;; *) - os=netbsd + os=netbsd ;; esac # The OS release @@ -223,7 +222,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on @@ -269,7 +268,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit ;; + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead @@ -295,7 +297,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo s390-ibm-zvmoe exit ;; *:OS400:*:*) - echo powerpc-ibm-os400 + echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} @@ -324,14 +326,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize @@ -375,23 +396,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} - exit ;; + exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; @@ -461,8 +482,8 @@ EOF echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ @@ -475,7 +496,7 @@ EOF else echo i586-dg-dgux${UNAME_RELEASE} fi - exit ;; + exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; @@ -532,7 +553,7 @@ EOF echo rs6000-ibm-aix3.2 fi exit ;; - *:AIX:*:[45]) + *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 @@ -575,52 +596,52 @@ EOF 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac + esac ;; + esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + sed 's/^ //' << EOF >$dummy.c - #define _HPUX_SOURCE - #include - #include + #define _HPUX_SOURCE + #include + #include - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa @@ -640,7 +661,7 @@ EOF # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep __LP64__ >/dev/null + grep -q __LP64__ then HP_ARCH="hppa2.0w" else @@ -711,22 +732,22 @@ EOF exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit ;; + exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit ;; + exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit ;; + exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit ;; + exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit ;; + exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; @@ -750,14 +771,14 @@ EOF exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} @@ -769,13 +790,12 @@ EOF echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) - case ${UNAME_MACHINE} in - pc98) - echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) @@ -784,25 +804,34 @@ EOF *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; - *:Interix*:[3456]*) - case ${UNAME_MACHINE} in + *:Interix*:*) + case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; - EM64T | authenticamd) + authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we @@ -832,20 +861,68 @@ EOF i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; - arm*:Linux:*:*) + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) - echo cris-axis-linux-gnu + echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; crisv32:Linux:*:*) - echo crisv32-axis-linux-gnu + echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; frv:Linux:*:*) - echo frv-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu @@ -856,74 +933,33 @@ EOF m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - mips:Linux:*:*) + mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU - #undef mips - #undef mipsel + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mipsel + CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips + CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips64 - #undef mips64el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mips64el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips64 - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) - echo or32-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu + padre:Linux:*:*) + echo sparc-unknown-linux-gnu exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level @@ -933,14 +969,17 @@ EOF *) echo hppa-unknown-linux-gnu ;; esac exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu @@ -948,78 +987,18 @@ EOF sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - xtensa:Linux:*:*) - echo xtensa-unknown-linux-gnu + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - # Set LC_ALL=C to ensure ld outputs messages in English. - ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit ;; - esac - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif - #else - #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) - LIBC=gnu - #else - LIBC=gnuaout - #endif - #endif - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^LIBC/{ - s: ::g - p - }'`" - test x"${LIBC}" != x && { - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit - } - test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } - ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both @@ -1027,11 +1006,11 @@ EOF echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. + # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) @@ -1048,7 +1027,7 @@ EOF i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) @@ -1063,7 +1042,7 @@ EOF fi exit ;; i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. + # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; @@ -1091,10 +1070,13 @@ EOF exit ;; pc:*:*:*) # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit ;; + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; @@ -1129,8 +1111,18 @@ EOF /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; @@ -1143,7 +1135,7 @@ EOF rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) @@ -1163,10 +1155,10 @@ EOF echo ns32k-sni-sysv fi exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm @@ -1192,11 +1184,11 @@ EOF exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv${UNAME_RELEASE} else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv${UNAME_RELEASE} fi - exit ;; + exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; @@ -1206,6 +1198,9 @@ EOF BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; @@ -1233,6 +1228,16 @@ EOF *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} @@ -1248,6 +1253,9 @@ EOF *:QNX:*:4*) echo i386-pc-qnx exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; @@ -1293,13 +1301,13 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` + UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; @@ -1314,6 +1322,12 @@ EOF i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 @@ -1336,11 +1350,11 @@ main () #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 - "4" + "4" #else - "" + "" #endif - ); exit (0); + ); exit (0); #endif #endif @@ -1474,9 +1488,9 @@ This script, last modified $timestamp, has failed to recognize the operating system you are using. It is advised that you download the most up to date version of the config scripts from - http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD and - http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD If the version you run ($0) is already up to date, please send the following data and any information you think might be diff --git a/config.h.in b/config.h.in index 7c85111..6580e95 100644 --- a/config.h.in +++ b/config.h.in @@ -1,9 +1,9 @@ /* config.h.in. Generated from configure.ac by autoheader. */ -/* the name of */ +/* the name of */ #undef HASH_MAP_CLASS -/* the location of */ +/* the location of or */ #undef HASH_MAP_H /* the namespace of hash_map/hash_set */ @@ -12,7 +12,7 @@ /* the name of */ #undef HASH_SET_CLASS -/* the location of */ +/* the location of or */ #undef HASH_SET_H /* Define to 1 if you have the header file. */ diff --git a/config.sub b/config.sub index 1761d8b..c894da4 100755 --- a/config.sub +++ b/config.sub @@ -1,10 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. -timestamp='2007-06-28' +timestamp='2012-02-10' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -21,9 +21,7 @@ timestamp='2007-06-28' # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -32,13 +30,16 @@ timestamp='2007-06-28' # Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. +# diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. @@ -72,7 +73,8 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -120,12 +122,18 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ - uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] @@ -148,10 +156,13 @@ case $os in -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray) + -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; + -bluegene*) + os=-cnk + ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 @@ -166,10 +177,10 @@ case $os in os=-chorusos basic_machine=$1 ;; - -chorusrdb) - os=-chorusrdb + -chorusrdb) + os=-chorusrdb basic_machine=$1 - ;; + ;; -hiux*) os=-hiuxwe2 ;; @@ -238,24 +249,32 @@ case $basic_machine in # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ + | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ + | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep \ + | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ - | mips64vr | mips64vrel \ + | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ @@ -268,29 +287,42 @@ case $basic_machine in | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | moxie \ | mt \ | msp430 \ + | nds32 | nds32le | nds32be \ | nios | nios2 \ | ns16k | ns32k \ + | open8 \ | or32 \ | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ + | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu | strongarm \ - | tahoe | thumb | tic4x | tic80 | tron \ - | v850 | v850e \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ - | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ - | z8k) + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) basic_machine=$basic_machine-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; @@ -300,6 +332,21 @@ case $basic_machine in basic_machine=mt-unknown ;; + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. @@ -314,29 +361,36 @@ case $basic_machine in # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ + | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ + | be32-* | be64-* \ | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ + | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ @@ -351,27 +405,36 @@ case $basic_machine in | mmix-* \ | mt-* \ | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ - | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ | tron-* \ - | v850-* | v850e-* | vax-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ - | xstormy16-* | xtensa-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ | ymp-* \ - | z8k-*) + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. @@ -389,7 +452,7 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; - abacus) + abacus) basic_machine=abacus-unknown ;; adobe68k) @@ -435,6 +498,10 @@ case $basic_machine in basic_machine=m68k-apollo os=-bsd ;; + aros) + basic_machine=i386-pc + os=-aros + ;; aux) basic_machine=m68k-apple os=-aux @@ -443,10 +510,35 @@ case $basic_machine in basic_machine=ns32k-sequent os=-dynix ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; c90) basic_machine=c90-cray os=-unicos ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; convex-c1) basic_machine=c1-convex os=-bsd @@ -475,7 +567,7 @@ case $basic_machine in basic_machine=craynv-cray os=-unicosmp ;; - cr16) + cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; @@ -514,6 +606,10 @@ case $basic_machine in basic_machine=m88k-motorola os=-sysv3 ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp @@ -629,7 +725,6 @@ case $basic_machine in i370-ibm* | ibm*) basic_machine=i370-ibm ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 @@ -668,6 +763,14 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; m88k-omron*) basic_machine=m88k-omron ;; @@ -679,6 +782,9 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; + microblaze) + basic_machine=microblaze-xilinx + ;; mingw32) basic_machine=i386-pc os=-mingw32 @@ -715,10 +821,18 @@ case $basic_machine in ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; + msys) + basic_machine=i386-pc + os=-msys + ;; mvs) basic_machine=i370-ibm os=-mvs ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; ncr3000) basic_machine=i486-ncr os=-sysv4 @@ -783,6 +897,12 @@ case $basic_machine in np1) basic_machine=np1-gould ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -813,6 +933,14 @@ case $basic_machine in basic_machine=i860-intel os=-osf ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; pbd) basic_machine=sparc-tti ;; @@ -857,9 +985,10 @@ case $basic_machine in ;; power) basic_machine=power-ibm ;; - ppc) basic_machine=powerpc-unknown + ppc | ppcbe) basic_machine=powerpc-unknown ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown @@ -953,6 +1082,9 @@ case $basic_machine in basic_machine=i860-stratus os=-sysv4 ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; sun2) basic_machine=m68000-sun ;; @@ -1009,17 +1141,9 @@ case $basic_machine in basic_machine=t90-cray os=-unicos ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tic55x | c55x*) - basic_machine=tic55x-unknown - os=-coff - ;; - tic6x | c6x*) - basic_machine=tic6x-unknown - os=-coff + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown @@ -1088,6 +1212,9 @@ case $basic_machine in xps | xps100) basic_machine=xps100-honeywell ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; ymp) basic_machine=ymp-cray os=-unicos @@ -1096,6 +1223,10 @@ case $basic_machine in basic_machine=z8k-unknown os=-sim ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; none) basic_machine=none-none os=-none @@ -1134,7 +1265,7 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) @@ -1181,9 +1312,12 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases + # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; @@ -1204,10 +1338,11 @@ case $os in # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ + | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ @@ -1216,9 +1351,10 @@ case $os in | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ @@ -1226,7 +1362,7 @@ case $os in | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1265,7 +1401,7 @@ case $os in -opened*) os=-openedition ;; - -os400*) + -os400*) os=-os400 ;; -wince*) @@ -1314,7 +1450,7 @@ case $os in -sinix*) os=-sysv4 ;; - -tpf*) + -tpf*) os=-tpf ;; -triton*) @@ -1356,6 +1492,11 @@ case $os in -zvmoe) os=-zvmoe ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; -none) ;; *) @@ -1378,10 +1519,10 @@ else # system, and we'll never get to this point. case $basic_machine in - score-*) + score-*) os=-elf ;; - spu-*) + spu-*) os=-elf ;; *-acorn) @@ -1393,8 +1534,17 @@ case $basic_machine in arm*-semi) os=-aout ;; - c4x-* | tic4x-*) - os=-coff + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff ;; # This must come before the *-dec entry. pdp10-*) @@ -1414,14 +1564,11 @@ case $basic_machine in ;; m68000-sun) os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 ;; m68*-cisco) os=-aout ;; - mep-*) + mep-*) os=-elf ;; mips*-cisco) @@ -1448,7 +1595,7 @@ case $basic_machine in *-ibm) os=-aix ;; - *-knuth) + *-knuth) os=-mmixware ;; *-wec) @@ -1553,7 +1700,7 @@ case $basic_machine in -sunos*) vendor=sun ;; - -aix*) + -cnk*|-aix*) vendor=ibm ;; -beos*) diff --git a/configure b/configure index 5802f1c..224934a 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for Protocol Buffers 2.3.0. +# Generated by GNU Autoconf 2.68 for Protocol Buffers 2.6.0. # # Report bugs to . # @@ -174,7 +174,15 @@ test x\$exitcode = x0 || exit 1" as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 -test \$(( 1 + 1 )) = 2 || exit 1" +test \$(( 1 + 1 )) = 2 || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else @@ -536,155 +544,8 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -# Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} -case X$lt_ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','` - ;; -esac - -ECHO=${lt_ECHO-echo} -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then - # Yippee, $ECHO works! - : -else - # Restart under the correct shell. - exec $SHELL "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat <<_LT_EOF -$* -_LT_EOF - exit 0 -fi - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -if test -z "$lt_ECHO"; then - if test "X${echo_test_string+set}" != Xset; then - # find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if { echo_test_string=`eval $cmd`; } 2>/dev/null && - { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null - then - break - fi - done - fi - - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : - else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$ECHO" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - ECHO='print -r' - elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} - else - # Try using printf. - ECHO='printf %s\n' - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - ECHO="$CONFIG_SHELL $0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$CONFIG_SHELL $0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do - if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null - then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "$0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} - else - # Oops. We lost completely, so just stick with echo. - ECHO=echo - fi - fi - fi - fi - fi -fi - -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -lt_ECHO=$ECHO -if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then - lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" -fi - - - test -n "$DJDIR" || exec 7<&0 &1 @@ -709,8 +570,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='Protocol Buffers' PACKAGE_TARNAME='protobuf' -PACKAGE_VERSION='2.3.0' -PACKAGE_STRING='Protocol Buffers 2.3.0' +PACKAGE_VERSION='2.6.0' +PACKAGE_STRING='Protocol Buffers 2.6.0' PACKAGE_BUGREPORT='protobuf@googlegroups.com' PACKAGE_URL='' @@ -772,9 +633,12 @@ OTOOL LIPO NMEDIT DSYMUTIL -lt_ECHO +MANIFEST_TOOL RANLIB +ac_ct_AR AR +DLLTOOL +OBJDUMP LN_S NM ac_ct_DUMPBIN @@ -848,6 +712,9 @@ build_os build_vendor build_cpu build +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE target_alias host_alias build_alias @@ -889,6 +756,7 @@ SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking +enable_maintainer_mode with_zlib with_protoc enable_dependency_tracking @@ -898,6 +766,7 @@ enable_static with_pic enable_fast_install with_gnu_ld +with_sysroot enable_libtool_lock ' ac_precious_vars='build_alias @@ -1454,7 +1323,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures Protocol Buffers 2.3.0 to adapt to many kinds of systems. +\`configure' configures Protocol Buffers 2.6.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1525,7 +1394,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Protocol Buffers 2.3.0:";; + short | recursive ) echo "Configuration of Protocol Buffers 2.6.0:";; esac cat <<\_ACEOF @@ -1533,6 +1402,8 @@ Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-maintainer-mode disable make rules and dependencies not useful + (and sometimes confusing) to the casual installer --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --disable-64bit-solaris Build 64 bit binary on Solaris [default=on] @@ -1550,9 +1421,11 @@ Optional Packages: --with-protoc=COMMAND use the given protoc command instead of building a new one when building tests (useful for cross-compiling) - --with-pic try to use only PIC/non-PIC objects [default=use + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot=DIR Search for dependent libraries within DIR + (or the compiler's sysroot if not specified). Some influential environment variables: CC C compiler command @@ -1632,7 +1505,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Protocol Buffers configure 2.3.0 +Protocol Buffers configure 2.6.0 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -2229,7 +2102,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Protocol Buffers $as_me 2.3.0, which was +It was created by Protocol Buffers $as_me 2.6.0, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -2579,6 +2452,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + ac_config_headers="$ac_config_headers config.h" @@ -3171,7 +3067,7 @@ fi # Define the identity of the package. PACKAGE='protobuf' - VERSION='2.3.0' + VERSION='2.6.0' cat >>confdefs.h <<_ACEOF @@ -5243,8 +5139,8 @@ esac -macro_version='2.2.4' -macro_revision='1.2976' +macro_version='2.4.2' +macro_revision='1.3337' @@ -5260,6 +5156,75 @@ macro_revision='1.2976' ltmain="$ac_aux_dir/ltmain.sh" +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : @@ -5595,8 +5560,11 @@ if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. - if test -n "$ac_tool_prefix"; then - for ac_prog in "dumpbin -symbols" "link -dump -symbols" + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 @@ -5640,7 +5608,7 @@ fi fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN - for ac_prog in "dumpbin -symbols" "link -dump -symbols" + for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -5695,6 +5663,15 @@ esac fi fi + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" @@ -5714,13 +5691,13 @@ if ${lt_cv_nm_interface+:} false; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:5717: $ac_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:5720: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:5723: output\"" >&5) + (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -5766,7 +5743,7 @@ else lt_cv_sys_max_cmd_len=-1; ;; - cygwin* | mingw*) + cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, @@ -5777,6 +5754,11 @@ else lt_cv_sys_max_cmd_len=8192; ;; + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. @@ -5802,6 +5784,11 @@ else lt_cv_sys_max_cmd_len=196608 ;; + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not @@ -5841,8 +5828,8 @@ else # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ - = "XX$teststring$teststring"; } >/dev/null 2>&1 && + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` @@ -5884,8 +5871,8 @@ $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,, \ + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes @@ -5934,6 +5921,80 @@ esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : @@ -5950,6 +6011,11 @@ case $reload_flag in esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' @@ -5967,6 +6033,107 @@ esac +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } @@ -6012,15 +6179,23 @@ mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. - if ( file / ) >/dev/null 2>&1; then + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; @@ -6045,6 +6220,10 @@ gnu*) lt_cv_deplibs_check_method=pass_all ;; +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in @@ -6053,11 +6232,11 @@ hpux10.20* | hpux11*) lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac @@ -6078,12 +6257,12 @@ irix5* | irix6* | nonstopux*) lt_cv_deplibs_check_method=pass_all ;; -# This must be Linux ELF. -linux* | k*bsd*-gnu) +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; -netbsd*) +netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else @@ -6160,6 +6339,21 @@ esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown @@ -6175,12 +6369,165 @@ test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. -set dummy ${ac_tool_prefix}ar; ac_word=$2 + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AR+:} false; then : +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then @@ -6193,7 +6540,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_AR="${ac_tool_prefix}ar" + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -6213,11 +6560,15 @@ $as_echo "no" >&6; } fi + test -n "$AR" && break + done fi -if test -z "$ac_cv_prog_AR"; then +if test -z "$AR"; then ac_ct_AR=$AR - # Extract the first word of "ar", so it can be a program name with args. -set dummy ar; ac_word=$2 + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : @@ -6233,7 +6584,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_AR="ar" + ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -6252,6 +6603,10 @@ else $as_echo "no" >&6; } fi + + test -n "$ac_ct_AR" && break +done + if test "x$ac_ct_AR" = x; then AR="false" else @@ -6263,16 +6618,72 @@ ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi -else - AR="$ac_cv_prog_AR" fi -test -z "$AR" && AR=ar -test -z "$AR_FLAGS" && AR_FLAGS=cru +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi @@ -6486,15 +6897,27 @@ old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + @@ -6559,7 +6982,7 @@ case $host_os in aix*) symcode='[BCDT]' ;; -cygwin* | mingw* | pw32*) +cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) @@ -6602,8 +7025,8 @@ esac lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -6627,6 +7050,7 @@ for ac_symprfx in "" "_"; do # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ @@ -6639,6 +7063,7 @@ for ac_symprfx in "" "_"; do else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no @@ -6664,8 +7089,8 @@ _LT_EOF test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 - (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then @@ -6680,6 +7105,18 @@ _LT_EOF if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + #ifdef __cplusplus extern "C" { #endif @@ -6691,7 +7128,7 @@ _LT_EOF cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ -const struct { +LT_DLSYM_CONST struct { const char *name; void *address; } @@ -6717,8 +7154,8 @@ static const void *lt_preloaded_setup() { _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext - lt_save_LIBS="$LIBS" - lt_save_CFLAGS="$CFLAGS" + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 @@ -6728,8 +7165,8 @@ _LT_EOF test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi - LIBS="$lt_save_LIBS" - CFLAGS="$lt_save_CFLAGS" + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi @@ -6766,6 +7203,20 @@ else $as_echo "ok" >&6; } fi +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + @@ -6785,6 +7236,41 @@ fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 +$as_echo "${with_sysroot}" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + @@ -6819,7 +7305,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 6822 "configure"' > conftest.$ac_ext + echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -6954,7 +7440,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } CFLAGS="$SAVE_CFLAGS" fi ;; -sparc*-*solaris*) +*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 @@ -6965,7 +7451,20 @@ sparc*-*solaris*) case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in - yes*) LD="${LD-ld} -m elf64_sparc" ;; + yes*) + case $host in + i?86-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD="${LD-ld}_sol2" + fi + ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" @@ -6981,19 +7480,16 @@ esac need_locks="$enable_libtool_lock" - - case $host_os in - rhapsody* | darwin*) - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. -set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DSYMUTIL+:} false; then : +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$DSYMUTIL"; then - ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH @@ -7002,7 +7498,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -7012,10 +7508,10 @@ IFS=$as_save_IFS fi fi -DSYMUTIL=$ac_cv_prog_DSYMUTIL -if test -n "$DSYMUTIL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 -$as_echo "$DSYMUTIL" >&6; } +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } @@ -7023,17 +7519,17 @@ fi fi -if test -z "$ac_cv_prog_DSYMUTIL"; then - ac_ct_DSYMUTIL=$DSYMUTIL - # Extract the first word of "dsymutil", so it can be a program name with args. -set dummy dsymutil; ac_word=$2 +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$ac_ct_DSYMUTIL"; then - ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH @@ -7042,7 +7538,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -7052,17 +7548,17 @@ IFS=$as_save_IFS fi fi -ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL -if test -n "$ac_ct_DSYMUTIL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 -$as_echo "$ac_ct_DSYMUTIL" >&6; } +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - if test "x$ac_ct_DSYMUTIL" = x; then - DSYMUTIL=":" + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) @@ -7070,22 +7566,50 @@ yes:) $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac - DSYMUTIL=$ac_ct_DSYMUTIL + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else - DSYMUTIL="$ac_cv_prog_DSYMUTIL" + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi + + + + + + case $host_os in + rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. -set dummy ${ac_tool_prefix}nmedit; ac_word=$2 + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_NMEDIT+:} false; then : +if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$NMEDIT"; then - ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH @@ -7094,7 +7618,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -7104,10 +7628,10 @@ IFS=$as_save_IFS fi fi -NMEDIT=$ac_cv_prog_NMEDIT -if test -n "$NMEDIT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 -$as_echo "$NMEDIT" >&6; } +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } @@ -7115,10 +7639,102 @@ fi fi -if test -z "$ac_cv_prog_NMEDIT"; then - ac_ct_NMEDIT=$NMEDIT - # Extract the first word of "nmedit", so it can be a program name with args. -set dummy nmedit; ac_word=$2 +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : @@ -7488,7 +8104,13 @@ else $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? - if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 @@ -7499,6 +8121,7 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : @@ -7519,591 +8142,111 @@ main () return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - lt_cv_ld_exported_symbols_list=yes -else - lt_cv_ld_exported_symbols_list=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 -$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } - case $host_os in - rhapsody* | darwin1.[012]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; - darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - darwin*) # darwin 5.x on - # if running on 10.5 or later, the deployment target defaults - # to the OS version, if on x86, and 10.4, the deployment - # target defaults to 10.4. Don't you love it? - case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in - 10.0,*86*-darwin8*|10.0,*-darwin[91]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[012]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - esac - ;; - esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then - _lt_dar_single_mod='$single_module' - fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' - else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - if test "$DSYMUTIL" != ":"; then - _lt_dsymutil='~$DSYMUTIL $lib || :' - else - _lt_dsymutil= - fi - ;; - esac - -for ac_header in dlfcn.h -do : - ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default -" -if test "x$ac_cv_header_dlfcn_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_DLFCN_H 1 -_ACEOF - -fi - -done - - - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -if test -z "$CXX"; then - if test -n "$CCC"; then - CXX=$CCC - else - if test -n "$ac_tool_prefix"; then - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CXX=$ac_cv_prog_CXX -if test -n "$CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 -$as_echo "$CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CXX" && break - done -fi -if test -z "$CXX"; then - ac_ct_CXX=$CXX - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CXX"; then - ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CXX="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CXX=$ac_cv_prog_ac_ct_CXX -if test -n "$ac_ct_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 -$as_echo "$ac_ct_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CXX" && break -done - - if test "x$ac_ct_CXX" = x; then - CXX="g++" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_ct_CXX - fi -fi - - fi -fi -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 -$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } -if ${ac_cv_cxx_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_cxx_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 -$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GXX=yes -else - GXX= -fi -ac_test_CXXFLAGS=${CXXFLAGS+set} -ac_save_CXXFLAGS=$CXXFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 -$as_echo_n "checking whether $CXX accepts -g... " >&6; } -if ${ac_cv_prog_cxx_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_cxx_werror_flag=$ac_cxx_werror_flag - ac_cxx_werror_flag=yes - ac_cv_prog_cxx_g=no - CXXFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_prog_cxx_g=yes -else - CXXFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -else - ac_cxx_werror_flag=$ac_save_cxx_werror_flag - CXXFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_prog_cxx_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cxx_werror_flag=$ac_save_cxx_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 -$as_echo "$ac_cv_prog_cxx_g" >&6; } -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS=$ac_save_CXXFLAGS -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -depcc="$CXX" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CXX_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CXX_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok `-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CXX_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CXX_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } -CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then - am__fastdepCXX_TRUE= - am__fastdepCXX_FALSE='#' -else - am__fastdepCXX_TRUE='#' - am__fastdepCXX_FALSE= -fi - - -if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 -$as_echo_n "checking how to run the C++ preprocessor... " >&6; } -if test -z "$CXXCPP"; then - if ${ac_cv_prog_CXXCPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CXXCPP needs to be expanded - for CXXCPP in "$CXX -E" "/lib/cpp" - do - ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" - done - ac_cv_prog_CXXCPP=$CXXCPP - -fi - CXXCPP=$ac_cv_prog_CXXCPP -else - ac_cv_prog_CXXCPP=$CXXCPP fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 -$as_echo "$CXXCPP" >&6; } -ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 else - # Broken: fails on valid input. -continue + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + fi -rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 _ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break + fi -rm -f conftest.err conftest.i conftest.$ac_ext done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -_lt_caught_CXX_error=yes; } -fi -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -else - _lt_caught_CXX_error=yes -fi +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf + @@ -8183,7 +8326,22 @@ fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : - withval=$with_pic; pic_mode="$withval" + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for lt_pkg in $withval; do + IFS="$lt_save_ifs" + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac else pic_mode=default fi @@ -8260,6 +8418,11 @@ LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + test -z "$LN_S" && LN_S="ln -s" @@ -8309,19 +8472,6 @@ _ACEOF - - - - - - - - - - - - - case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some @@ -8334,23 +8484,6 @@ aix3*) ;; esac -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s/\(["`$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - # Global variables: ofile=libtool can_build_shared=yes @@ -8379,7 +8512,7 @@ for cc_temp in $compiler""; do *) break;; esac done -cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it @@ -8588,7 +8721,12 @@ if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then - lt_prog_compiler_no_builtin_flag=' -fno-builtin' + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } @@ -8608,15 +8746,15 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8611: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8615: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes @@ -8645,8 +8783,6 @@ fi lt_prog_compiler_pic= lt_prog_compiler_static= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 -$as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' @@ -8680,7 +8816,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # PIC is the default for these OSes. ;; - mingw* | cygwin* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style @@ -8694,11 +8830,18 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_pic='-fno-common' ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. case $host_cpu in - hppa*64*|ia64*) + hppa*64*) # +Z the default ;; *) @@ -8735,6 +8878,15 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_pic='-fPIC' ;; esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in @@ -8748,7 +8900,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } fi ;; - mingw* | cygwin* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' @@ -8776,14 +8928,34 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_static='-non_shared' ;; - linux* | k*bsd*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in - icc* | ecc* | ifort*) + # old Intel for x86_64 which still supported -KPIC. + ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; - pgcc* | pgf77* | pgf90* | pgf95*) + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' @@ -8795,25 +8967,40 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; - xl*) - # IBM XL C 8.0/Fortran 10.1 on PPC + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; - *Sun\ F*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - lt_prog_compiler_pic='-KPIC' + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='' ;; esac ;; @@ -8845,7 +9032,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in - f77* | f90* | f95*) + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; @@ -8902,13 +9089,17 @@ case $host_os in lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 -$as_echo "$lt_prog_compiler_pic" >&6; } - - - - +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. @@ -8932,15 +9123,15 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8935: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8939: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes @@ -8969,6 +9160,11 @@ fi + + + + + # # Check to make sure the static flag actually works. # @@ -8988,7 +9184,7 @@ else if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 - $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes @@ -9037,16 +9233,16 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9040: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:9044: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes @@ -9092,16 +9288,16 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9095: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:9099: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes @@ -9167,7 +9363,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= - hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported @@ -9196,7 +9391,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie extract_expsyms_cmds= case $host_os in - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. @@ -9211,10 +9406,39 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie openbsd*) with_gnu_ld=no ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs=no + ;; esac ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' @@ -9232,6 +9456,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie fi supports_anon_versioning=no case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... @@ -9247,11 +9472,12 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie ld_shlibs=no cat <<_LT_EOF 1>&2 -*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. _LT_EOF fi @@ -9283,14 +9509,16 @@ _LT_EOF fi ;; - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' @@ -9308,6 +9536,11 @@ _LT_EOF fi ;; + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no @@ -9323,7 +9556,7 @@ _LT_EOF archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; - gnu* | linux* | tpf* | k*bsd*-gnu) + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in @@ -9333,15 +9566,16 @@ _LT_EOF if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then - tmp_addflag= + tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -9349,13 +9583,20 @@ _LT_EOF tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; - xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 @@ -9371,17 +9612,16 @@ _LT_EOF fi case $cc_basename in - xlf*) + xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' - hardcode_libdir_flag_spec= - hardcode_libdir_flag_spec_ld='-rpath $libdir' - archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -9390,13 +9630,13 @@ _LT_EOF fi ;; - netbsd*) + netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; @@ -9414,8 +9654,8 @@ _LT_EOF _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -9461,8 +9701,8 @@ _LT_EOF *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -9502,8 +9742,10 @@ _LT_EOF else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi @@ -9565,6 +9807,7 @@ _LT_EOF if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi + link_all_deplibs=no else # not using gcc if test "$host_cpu" = ia64; then @@ -9580,6 +9823,7 @@ _LT_EOF fi fi + export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes @@ -9589,7 +9833,13 @@ _LT_EOF allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -9602,25 +9852,32 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' @@ -9629,7 +9886,13 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi else # Determine the default libpath from the value encoded in an # empty executable. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -9642,30 +9905,42 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + fi + + aix_libpath=$lt_cv_aix_libpath_ fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec='$convenience' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' @@ -9692,25 +9967,69 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi export_dynamic_flag_spec=-rdynamic ;; - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_from_new_cmds='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' - enable_shared_with_static_runtimes=yes + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac ;; darwin* | rhapsody*) @@ -9720,11 +10039,20 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported - whole_archive_flag_spec='' + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" - if test "$GCC" = "yes"; then - output_verbose_link_cmd=echo + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" @@ -9742,10 +10070,6 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_shlibpath_var=no ;; - freebsd1*) - ld_shlibs=no - ;; - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little @@ -9758,7 +10082,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) + freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes @@ -9767,7 +10091,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) - archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no @@ -9775,7 +10099,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hpux9*) if test "$GCC" = yes; then - archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi @@ -9790,14 +10114,13 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes @@ -9809,16 +10132,16 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then + if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else @@ -9830,7 +10153,46 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + ;; esac fi @@ -9858,26 +10220,39 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -int foo(void) {} +int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' - + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" + LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test "$lt_cv_irix_exported_symbol" = yes; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' @@ -9886,7 +10261,7 @@ rm -f core conftest.err conftest.$ac_objext \ link_all_deplibs=yes ;; - netbsd*) + netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else @@ -9939,17 +10314,17 @@ rm -f core conftest.err conftest.$ac_objext \ hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported - archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' @@ -9959,13 +10334,13 @@ rm -f core conftest.err conftest.$ac_objext \ osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' @@ -9978,9 +10353,9 @@ rm -f core conftest.err conftest.$ac_objext \ no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' - archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) @@ -10168,44 +10543,50 @@ x|xyes) # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl - pic_flag=$lt_prog_compiler_pic - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag - allow_undefined_flag= - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - then - archive_cmds_need_lc=no - else - archive_cmds_need_lc=yes - fi - allow_undefined_flag=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 -$as_echo "$archive_cmds_need_lc" >&6; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi @@ -10363,11 +10744,6 @@ esac - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } @@ -10376,16 +10752,23 @@ if test "$GCC" = yes; then darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` - else - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= @@ -10398,7 +10781,7 @@ if test "$GCC" = yes; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done - lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; @@ -10418,7 +10801,13 @@ BEGIN {RS=" "; FS="/|\n";} { if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` - sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi @@ -10444,7 +10833,7 @@ need_version=unknown case $host_os in aix3*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH @@ -10453,7 +10842,7 @@ aix3*) ;; aix[4-9]*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes @@ -10506,7 +10895,7 @@ amigaos*) m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; @@ -10518,7 +10907,7 @@ beos*) ;; bsdi[45]*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' @@ -10531,14 +10920,15 @@ bsdi[45]*) # libtool to hard-code these into programs ;; -cygwin* | mingw* | pw32*) +cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) + case $GCC,$cc_basename in + yes,*) + # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ @@ -10559,36 +10949,83 @@ cygwin* | mingw* | pw32*) cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; - mingw*) + mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' ;; *) + # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' ;; esac - dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; @@ -10609,7 +11046,7 @@ darwin* | rhapsody*) ;; dgux*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' @@ -10617,10 +11054,6 @@ dgux*) shlibpath_var=LD_LIBRARY_PATH ;; -freebsd1*) - dynamic_linker=no - ;; - freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. @@ -10628,7 +11061,7 @@ freebsd* | dragonfly*) objformat=`/usr/bin/objformat` else case $host_os in - freebsd[123]*) objformat=aout ;; + freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi @@ -10646,7 +11079,7 @@ freebsd* | dragonfly*) esac shlibpath_var=LD_LIBRARY_PATH case $host_os in - freebsd2*) + freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) @@ -10666,12 +11099,26 @@ freebsd* | dragonfly*) ;; gnu*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -10717,12 +11164,14 @@ hpux9* | hpux10* | hpux11*) soname_spec='${libname}${release}${shared_ext}$major' ;; esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 ;; interix[3-9]*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' @@ -10738,7 +11187,7 @@ irix5* | irix6* | nonstopux*) nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; @@ -10775,9 +11224,9 @@ linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; -# This must be Linux ELF. -linux* | k*bsd*-gnu) - version_type=linux +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -10785,12 +11234,17 @@ linux* | k*bsd*-gnu) finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no + # Some binutils ld are patched to set DT_RUNPATH - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ - LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -10803,13 +11257,17 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : - shlibpath_overrides_runpath=yes + lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install @@ -10818,7 +11276,7 @@ rm -f core conftest.err conftest.$ac_objext \ # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi @@ -10831,6 +11289,18 @@ rm -f core conftest.err conftest.$ac_objext \ dynamic_linker='GNU/Linux ld.so' ;; +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + netbsd*) version_type=sunos need_lib_prefix=no @@ -10850,7 +11320,7 @@ netbsd*) ;; newsos6) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes @@ -10919,7 +11389,7 @@ rdos*) ;; solaris*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -10944,7 +11414,7 @@ sunos4*) ;; sysv4 | sysv4.3*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH @@ -10968,7 +11438,7 @@ sysv4 | sysv4.3*) sysv4*MP*) if test -d /usr/nec ;then - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH @@ -10999,17 +11469,17 @@ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_name_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH @@ -11121,6 +11591,11 @@ fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= @@ -11179,7 +11654,7 @@ else lt_cv_dlopen_self=yes ;; - mingw* | pw32*) + mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; @@ -11451,7 +11926,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11454 "configure" +#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11492,11 +11967,13 @@ else # endif #endif -#ifdef __cplusplus -extern "C" void exit (int); +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); #endif -void fnord() { int i=42;} +int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); @@ -11505,13 +11982,17 @@ int main () if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } /* dlclose (self); */ } else puts (dlerror ()); - exit (status); + return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 @@ -11551,7 +12032,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11554 "configure" +#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11592,11 +12073,13 @@ else # endif #endif -#ifdef __cplusplus -extern "C" void exit (int); +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); #endif -void fnord() { int i=42;} +int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); @@ -11605,13 +12088,17 @@ int main () if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } /* dlclose (self); */ } else puts (dlerror ()); - exit (status); + return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 @@ -11743,25 +12230,164 @@ $as_echo_n "checking whether to build shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 -$as_echo_n "checking whether to build static libraries... " >&6; } - # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 -$as_echo "$enable_static" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +CC="$lt_save_CC" + + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } fi + ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -CC="$lt_save_CC" - +else + _lt_caught_CXX_error=yes +fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' @@ -11778,7 +12404,6 @@ export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no hardcode_libdir_flag_spec_CXX= -hardcode_libdir_flag_spec_ld_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported @@ -11788,6 +12413,8 @@ module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds +reload_flag_CXX=$reload_flag +reload_cmds_CXX=$reload_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no @@ -11843,6 +12470,7 @@ $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX @@ -11860,6 +12488,7 @@ $RM -r conftest* fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC for cc_temp in $compiler""; do @@ -11870,7 +12499,7 @@ $RM -r conftest* *) break;; esac done -cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` if test -n "$compiler"; then @@ -11999,8 +12628,8 @@ with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' @@ -12032,7 +12661,7 @@ with_gnu_ld=$lt_cv_prog_gnu_ld # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no @@ -12131,6 +12760,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie fi fi + export_dynamic_flag_spec_CXX='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. @@ -12141,7 +12771,13 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie allow_undefined_flag_CXX='-berok' # Determine the default libpath from the value encoded in an empty # executable. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -12154,26 +12790,33 @@ main () _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' @@ -12182,7 +12825,13 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi else # Determine the default libpath from the value encoded in an # empty executable. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -12195,30 +12844,42 @@ main () _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' ${wl}-bernotok' allow_undefined_flag_CXX=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_CXX='$convenience' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + fi archive_cmds_need_lc_CXX=yes # This is similar to how AIX traditionally builds its shared # libraries. @@ -12247,29 +12908,76 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi esac ;; - cygwin* | mingw* | pw32*) - # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_CXX='-L$libdir' - allow_undefined_flag_CXX=unsupported - always_export_symbols_CXX=no - enable_shared_with_static_runtimes_CXX=yes - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs_CXX=no - fi - ;; + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_CXX=' ' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=yes + file_list_spec_CXX='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' + enable_shared_with_static_runtimes_CXX=yes + # Don't use ranlib + old_postinstall_cmds_CXX='chmod 644 $oldlib' + postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-all-symbols' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + esac + ;; darwin* | rhapsody*) @@ -12277,11 +12985,20 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported - whole_archive_flag_spec_CXX='' + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec_CXX='' + fi link_all_deplibs_CXX=yes allow_undefined_flag_CXX="$_lt_dar_allow_undefined" - if test "$GCC" = "yes"; then - output_verbose_link_cmd=echo + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" @@ -12315,7 +13032,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi esac ;; - freebsd[12]*) + freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no @@ -12334,6 +13051,11 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi gnu*) ;; + haiku*) + archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs_CXX=yes + ;; + hpux9*) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: @@ -12358,11 +13080,11 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then - archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no @@ -12423,7 +13145,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then @@ -12433,10 +13155,10 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi @@ -12466,7 +13188,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi case $cc_basename in CC*) # SGI C++ - archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is @@ -12477,9 +13199,9 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib' + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes @@ -12490,7 +13212,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi inherit_rpath_CXX=yes ;; - linux* | k*bsd*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler @@ -12508,7 +13230,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' @@ -12545,26 +13267,26 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in - *pgCC\ [1-5]* | *pgcpp\ [1-5]*) + *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; - *) # Version 6 will use weak symbols + *) # Version 6 and above use weak symbols archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; @@ -12572,7 +13294,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ @@ -12591,9 +13313,9 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; - xl*) + xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' @@ -12613,13 +13335,13 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' - whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. - output_verbose_link_cmd='echo' + output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is @@ -12688,7 +13410,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi export_dynamic_flag_spec_CXX='${wl}-E' whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi - output_verbose_link_cmd=echo + output_verbose_link_cmd=func_echo_all else ld_shlibs_CXX=no fi @@ -12723,15 +13445,15 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi case $host in osf3*) allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; @@ -12747,17 +13469,17 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) - archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) - archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac @@ -12767,7 +13489,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support @@ -12803,7 +13525,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi solaris*) case $cc_basename in - CC*) + CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' @@ -12824,7 +13546,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi esac link_all_deplibs_CXX=yes - output_verbose_link_cmd='echo' + output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is @@ -12844,14 +13566,14 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi if test "$GXX" = yes && test "$with_gnu_ld" = no; then no_undefined_flag_CXX=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. @@ -12862,7 +13584,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' @@ -12916,6 +13638,10 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi CC*) archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ + '"$old_archive_cmds_CXX" + reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ + '"$reload_cmds_CXX" ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' @@ -12977,6 +13703,14 @@ private: }; _LT_EOF + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -12990,7 +13724,7 @@ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do - case $p in + case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. @@ -12999,13 +13733,22 @@ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 test $p = "-R"; then prev=$p continue - else - prev= fi + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac if test "$pre_test_object_deps_done" = no; then - case $p in - -L* | -R*) + case ${prev} in + -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. @@ -13025,8 +13768,10 @@ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 postdeps_CXX="${postdeps_CXX} ${prev}${p}" fi fi + prev= ;; + *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. @@ -13062,6 +13807,7 @@ else fi $RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken case $host_os in @@ -13097,7 +13843,7 @@ linux*) solaris*) case $cc_basename in - CC*) + CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as @@ -13162,8 +13908,6 @@ fi lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 -$as_echo_n "checking for $compiler option to produce PIC... " >&6; } # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then @@ -13197,7 +13941,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; - mingw* | cygwin* | os2* | pw32*) + mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style @@ -13213,6 +13957,11 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static_CXX= + ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. @@ -13223,10 +13972,11 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } fi ;; hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. case $host_cpu in - hppa*64*|ia64*) + hppa*64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' @@ -13261,6 +14011,11 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } ;; esac ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; dgux*) case $cc_basename in ec++*) @@ -13317,19 +14072,26 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } ;; esac ;; - linux* | k*bsd*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; - icpc* | ecpc* ) - # Intel C++ + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + lt_prog_compiler_static_CXX='-static' + ;; pgCC* | pgcpp*) # Portland Group C++ compiler lt_prog_compiler_wl_CXX='-Wl,' @@ -13343,8 +14105,8 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; - xlc* | xlC*) - # IBM XL 8.0 on PPC + xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-qpic' lt_prog_compiler_static_CXX='-qstaticlink' @@ -13374,7 +14136,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } ;; esac ;; - netbsd*) + netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise @@ -13406,7 +14168,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } ;; solaris*) case $cc_basename in - CC*) + CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' @@ -13471,10 +14233,17 @@ case $host_os in lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_CXX" >&5 -$as_echo "$lt_prog_compiler_pic_CXX" >&6; } - +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } +lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX # # Check to make sure the PIC flag actually works. @@ -13498,15 +14267,15 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13501: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:13505: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes @@ -13532,6 +14301,8 @@ fi + + # # Check to make sure the static flag actually works. # @@ -13551,7 +14322,7 @@ else if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 - $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes @@ -13597,16 +14368,16 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13600: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:13604: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes @@ -13649,16 +14420,16 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13652: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:13656: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes @@ -13709,27 +14480,40 @@ fi $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX="$ltdll_cmds" - ;; - cygwin* | mingw*) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' - ;; + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs_CXX=no + ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; + ;; esac - exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } @@ -13761,44 +14545,50 @@ x|xyes) # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext +if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_CXX - pic_flag=$lt_prog_compiler_pic_CXX - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_CXX - allow_undefined_flag_CXX= - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - then - archive_cmds_need_lc_CXX=no - else - archive_cmds_need_lc_CXX=yes - fi - allow_undefined_flag_CXX=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc_CXX" >&5 -$as_echo "$archive_cmds_need_lc_CXX" >&6; } + then + lt_cv_archive_cmds_need_lc_CXX=no + else + lt_cv_archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } + archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX ;; esac fi @@ -13866,8 +14656,6 @@ esac - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } @@ -13893,7 +14681,7 @@ need_version=unknown case $host_os in aix3*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH @@ -13902,7 +14690,7 @@ aix3*) ;; aix[4-9]*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes @@ -13955,7 +14743,7 @@ amigaos*) m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; @@ -13967,7 +14755,7 @@ beos*) ;; bsdi[45]*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' @@ -13980,14 +14768,15 @@ bsdi[45]*) # libtool to hard-code these into programs ;; -cygwin* | mingw* | pw32*) +cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) + case $GCC,$cc_basename in + yes,*) + # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ @@ -14008,36 +14797,82 @@ cygwin* | mingw* | pw32*) cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; - mingw*) + mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' ;; *) + # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' ;; esac - dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; @@ -14057,7 +14892,7 @@ darwin* | rhapsody*) ;; dgux*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' @@ -14065,10 +14900,6 @@ dgux*) shlibpath_var=LD_LIBRARY_PATH ;; -freebsd1*) - dynamic_linker=no - ;; - freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. @@ -14076,7 +14907,7 @@ freebsd* | dragonfly*) objformat=`/usr/bin/objformat` else case $host_os in - freebsd[123]*) objformat=aout ;; + freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi @@ -14094,7 +14925,7 @@ freebsd* | dragonfly*) esac shlibpath_var=LD_LIBRARY_PATH case $host_os in - freebsd2*) + freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) @@ -14114,12 +14945,26 @@ freebsd* | dragonfly*) ;; gnu*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -14165,12 +15010,14 @@ hpux9* | hpux10* | hpux11*) soname_spec='${libname}${release}${shared_ext}$major' ;; esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 ;; interix[3-9]*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' @@ -14186,7 +15033,7 @@ irix5* | irix6* | nonstopux*) nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; @@ -14223,9 +15070,9 @@ linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; -# This must be Linux ELF. -linux* | k*bsd*-gnu) - version_type=linux +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -14233,12 +15080,17 @@ linux* | k*bsd*-gnu) finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no + # Some binutils ld are patched to set DT_RUNPATH - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ - LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -14251,13 +15103,17 @@ main () _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : - shlibpath_overrides_runpath=yes + lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install @@ -14266,7 +15122,7 @@ rm -f core conftest.err conftest.$ac_objext \ # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi @@ -14279,6 +15135,18 @@ rm -f core conftest.err conftest.$ac_objext \ dynamic_linker='GNU/Linux ld.so' ;; +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + netbsd*) version_type=sunos need_lib_prefix=no @@ -14298,7 +15166,7 @@ netbsd*) ;; newsos6) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes @@ -14367,7 +15235,7 @@ rdos*) ;; solaris*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -14392,7 +15260,7 @@ sunos4*) ;; sysv4 | sysv4.3*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH @@ -14416,7 +15284,7 @@ sysv4 | sysv4.3*) sysv4*MP*) if test -d /usr/nec ;then - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH @@ -14447,17 +15315,17 @@ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_name_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH @@ -14518,6 +15386,8 @@ fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= @@ -14565,6 +15435,7 @@ fi fi # test -n "$compiler" CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC @@ -14593,6 +15464,8 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + ac_config_commands="$ac_config_commands libtool" @@ -15053,7 +15926,7 @@ fi if test "$with_protoc" != "no"; then : PROTOC=$with_protoc - if test "$with_protoc" == "yes"; then : + if test "$with_protoc" = "yes"; then : # No argument given. Use system protoc. PROTOC=protoc @@ -15576,6 +16449,77 @@ $as_echo "$as_me: WARNING: Impossible to determine how to use pthreads with shar acx_pthread_ok=no fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether what we have so far is sufficient with -nostdlib" >&5 +$as_echo_n "checking whether what we have so far is sufficient with -nostdlib... " >&6; } + CFLAGS="-nostdlib $CFLAGS" + # we need c with nostdlib + LIBS="$LIBS -lc" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + done=yes +else + done=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + if test "x$done" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + if test x"$done" = xno; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lpthread saves the day" >&5 +$as_echo_n "checking whether -lpthread saves the day... " >&6; } + LIBS="-lpthread $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + done=yes +else + done=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + if test "x$done" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + PTHREAD_LIBS="$PTHREAD_LIBS -lpthread" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Impossible to determine how to use pthreads with shared libraries and -nostdlib" >&5 +$as_echo "$as_me: WARNING: Impossible to determine how to use pthreads with shared libraries and -nostdlib" >&2;} + fi + fi + CFLAGS="$save_CFLAGS" LIBS="$save_LIBS" CC="$save_CC" @@ -15604,7 +16548,8 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the location of hash_map" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking the location of hash_map" >&5 $as_echo_n "checking the location of hash_map... " >&6; } ac_ext=cpp @@ -15613,44 +16558,81 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - ac_cv_cxx_hash_map_header="" - ac_cv_cxx_hash_map_class="" - for location in tr1/unordered_map ext/hash_map hash_map; do - for namespace in std::tr1 __gnu_cxx "" std stdext; do - for name in unordered_map hash_map; do - - if test -z "$ac_cv_cxx_hash_map_header"; then + ac_cv_cxx_hash_map="" + # First try unordered_map, but not on gcc's before 4.2 -- I've + # seen unexplainable unordered_map bugs with -O2 on older gcc's. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)) + # error GCC too old for unordered_map + #endif - # On OSX 1.5 / GCC 4.0.1 (the standard compiler on that platform), - # calling find() on a const unordered_map does not compile. So, we - # include a call to find() in our test to detect this broken - # implementation and avoid using it. Note that ext/hash_map works - # fine on this platform, so we'll end up using that. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +int +main () +{ +/* no program body necessary */ + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + stl_hash_old_gcc=no +else + stl_hash_old_gcc=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + for location in unordered_map tr1/unordered_map; do + for namespace in std std::tr1; do + if test -z "$ac_cv_cxx_hash_map" -a "$stl_hash_old_gcc" != yes; then + # Some older gcc's have a buggy tr1, so test a bit of code. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$location> int main () { -const ${namespace}::$name t; - t.find(1); +const ${namespace}::unordered_map t; + return t.find(5) == t.end(); ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_cxx_hash_map_header="<$location>"; - ac_cv_cxx_hash_namespace="$namespace"; - ac_cv_cxx_hash_map_class="$name"; + ac_cv_cxx_hash_map="<$location>"; + ac_cv_cxx_hash_namespace="$namespace"; + ac_cv_cxx_hash_map_class="unordered_map"; fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi - done + fi + done + done + # Now try hash_map + for location in ext/hash_map hash_map; do + for namespace in __gnu_cxx "" std stdext; do + if test -z "$ac_cv_cxx_hash_map"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$location> +int +main () +{ +${namespace}::hash_map t + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_cxx_hash_map="<$location>"; + ac_cv_cxx_hash_namespace="$namespace"; + ac_cv_cxx_hash_map_class="hash_map"; +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi done done - ac_cv_cxx_hash_set_header=`echo "$ac_cv_cxx_hash_map_header" | sed s/map/set/`; + ac_cv_cxx_hash_set=`echo "$ac_cv_cxx_hash_map" | sed s/map/set/`; ac_cv_cxx_hash_set_class=`echo "$ac_cv_cxx_hash_map_class" | sed s/map/set/`; - if test -n "$ac_cv_cxx_hash_map_header"; then + if test -n "$ac_cv_cxx_hash_map"; then $as_echo "#define HAVE_HASH_MAP 1" >>confdefs.h @@ -15659,31 +16641,31 @@ $as_echo "#define HAVE_HASH_SET 1" >>confdefs.h cat >>confdefs.h <<_ACEOF -#define HASH_MAP_H $ac_cv_cxx_hash_map_header +#define HASH_MAP_H $ac_cv_cxx_hash_map _ACEOF cat >>confdefs.h <<_ACEOF -#define HASH_SET_H $ac_cv_cxx_hash_set_header +#define HASH_SET_H $ac_cv_cxx_hash_set _ACEOF cat >>confdefs.h <<_ACEOF -#define HASH_MAP_CLASS $ac_cv_cxx_hash_map_class +#define HASH_NAMESPACE $ac_cv_cxx_hash_namespace _ACEOF cat >>confdefs.h <<_ACEOF -#define HASH_SET_CLASS $ac_cv_cxx_hash_set_class +#define HASH_MAP_CLASS $ac_cv_cxx_hash_map_class _ACEOF cat >>confdefs.h <<_ACEOF -#define HASH_NAMESPACE $ac_cv_cxx_hash_namespace +#define HASH_SET_CLASS $ac_cv_cxx_hash_set_class _ACEOF - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_hash_map_header" >&5 -$as_echo "$ac_cv_cxx_hash_map_header" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_hash_map" >&5 +$as_echo "$ac_cv_cxx_hash_map" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } @@ -15813,6 +16795,10 @@ LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' @@ -15837,10 +16823,6 @@ if test -z "${GCC_TRUE}" && test -z "${GCC_FALSE}"; then as_fn_error $? "conditional \"GCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${HAVE_ZLIB_TRUE}" && test -z "${HAVE_ZLIB_FALSE}"; then as_fn_error $? "conditional \"HAVE_ZLIB\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -16258,7 +17240,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Protocol Buffers $as_me 2.3.0, which was +This file was extended by Protocol Buffers $as_me 2.6.0, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16324,7 +17306,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -Protocol Buffers config.status 2.3.0 +Protocol Buffers config.status 2.6.0 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" @@ -16453,183 +17435,208 @@ AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' -macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' -macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' -enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' -enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' -pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' -enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' -host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' -host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' -host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' -build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' -build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' -build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' -SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' -Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' -GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' -EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' -FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' -LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' -NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' -LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' -max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' -ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' -exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' -lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' -lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' -lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' -reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' -reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' -deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' -file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' -AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' -AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' -STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' -RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' -old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' -CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' -CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' -compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' -GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' -objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' -SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' -ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' -MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' -need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' -DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' -NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' -LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' -OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' -OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' -libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' -shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' -extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' -archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' -enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' -export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' -whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' -compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' -archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' -archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' -module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' -module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' -with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' -allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' -no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' -inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' -link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' -fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' -always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' -export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' -exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' -include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' -prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' -file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' -variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' -need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' -need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' -version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' -runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' -shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' -shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' -libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' -library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' -soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' -postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' -finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' -sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' -sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' -enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' -enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' -enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' -old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' -striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' -compiler_lib_search_dirs='`$ECHO "X$compiler_lib_search_dirs" | $Xsed -e "$delay_single_quote_subst"`' -predep_objects='`$ECHO "X$predep_objects" | $Xsed -e "$delay_single_quote_subst"`' -postdep_objects='`$ECHO "X$postdep_objects" | $Xsed -e "$delay_single_quote_subst"`' -predeps='`$ECHO "X$predeps" | $Xsed -e "$delay_single_quote_subst"`' -postdeps='`$ECHO "X$postdeps" | $Xsed -e "$delay_single_quote_subst"`' -compiler_lib_search_path='`$ECHO "X$compiler_lib_search_path" | $Xsed -e "$delay_single_quote_subst"`' -LD_CXX='`$ECHO "X$LD_CXX" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_cmds_CXX='`$ECHO "X$old_archive_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' -compiler_CXX='`$ECHO "X$compiler_CXX" | $Xsed -e "$delay_single_quote_subst"`' -GCC_CXX='`$ECHO "X$GCC_CXX" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "X$lt_prog_compiler_no_builtin_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_wl_CXX='`$ECHO "X$lt_prog_compiler_wl_CXX" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_pic_CXX='`$ECHO "X$lt_prog_compiler_pic_CXX" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_static_CXX='`$ECHO "X$lt_prog_compiler_static_CXX" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_prog_compiler_c_o_CXX='`$ECHO "X$lt_cv_prog_compiler_c_o_CXX" | $Xsed -e "$delay_single_quote_subst"`' -archive_cmds_need_lc_CXX='`$ECHO "X$archive_cmds_need_lc_CXX" | $Xsed -e "$delay_single_quote_subst"`' -enable_shared_with_static_runtimes_CXX='`$ECHO "X$enable_shared_with_static_runtimes_CXX" | $Xsed -e "$delay_single_quote_subst"`' -export_dynamic_flag_spec_CXX='`$ECHO "X$export_dynamic_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`' -whole_archive_flag_spec_CXX='`$ECHO "X$whole_archive_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`' -compiler_needs_object_CXX='`$ECHO "X$compiler_needs_object_CXX" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_from_new_cmds_CXX='`$ECHO "X$old_archive_from_new_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_from_expsyms_cmds_CXX='`$ECHO "X$old_archive_from_expsyms_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' -archive_cmds_CXX='`$ECHO "X$archive_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' -archive_expsym_cmds_CXX='`$ECHO "X$archive_expsym_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' -module_cmds_CXX='`$ECHO "X$module_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' -module_expsym_cmds_CXX='`$ECHO "X$module_expsym_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' -with_gnu_ld_CXX='`$ECHO "X$with_gnu_ld_CXX" | $Xsed -e "$delay_single_quote_subst"`' -allow_undefined_flag_CXX='`$ECHO "X$allow_undefined_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`' -no_undefined_flag_CXX='`$ECHO "X$no_undefined_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec_CXX='`$ECHO "X$hardcode_libdir_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec_ld_CXX='`$ECHO "X$hardcode_libdir_flag_spec_ld_CXX" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_separator_CXX='`$ECHO "X$hardcode_libdir_separator_CXX" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_direct_CXX='`$ECHO "X$hardcode_direct_CXX" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_direct_absolute_CXX='`$ECHO "X$hardcode_direct_absolute_CXX" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_minus_L_CXX='`$ECHO "X$hardcode_minus_L_CXX" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_shlibpath_var_CXX='`$ECHO "X$hardcode_shlibpath_var_CXX" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_automatic_CXX='`$ECHO "X$hardcode_automatic_CXX" | $Xsed -e "$delay_single_quote_subst"`' -inherit_rpath_CXX='`$ECHO "X$inherit_rpath_CXX" | $Xsed -e "$delay_single_quote_subst"`' -link_all_deplibs_CXX='`$ECHO "X$link_all_deplibs_CXX" | $Xsed -e "$delay_single_quote_subst"`' -fix_srcfile_path_CXX='`$ECHO "X$fix_srcfile_path_CXX" | $Xsed -e "$delay_single_quote_subst"`' -always_export_symbols_CXX='`$ECHO "X$always_export_symbols_CXX" | $Xsed -e "$delay_single_quote_subst"`' -export_symbols_cmds_CXX='`$ECHO "X$export_symbols_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' -exclude_expsyms_CXX='`$ECHO "X$exclude_expsyms_CXX" | $Xsed -e "$delay_single_quote_subst"`' -include_expsyms_CXX='`$ECHO "X$include_expsyms_CXX" | $Xsed -e "$delay_single_quote_subst"`' -prelink_cmds_CXX='`$ECHO "X$prelink_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`' -file_list_spec_CXX='`$ECHO "X$file_list_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_action_CXX='`$ECHO "X$hardcode_action_CXX" | $Xsed -e "$delay_single_quote_subst"`' -compiler_lib_search_dirs_CXX='`$ECHO "X$compiler_lib_search_dirs_CXX" | $Xsed -e "$delay_single_quote_subst"`' -predep_objects_CXX='`$ECHO "X$predep_objects_CXX" | $Xsed -e "$delay_single_quote_subst"`' -postdep_objects_CXX='`$ECHO "X$postdep_objects_CXX" | $Xsed -e "$delay_single_quote_subst"`' -predeps_CXX='`$ECHO "X$predeps_CXX" | $Xsed -e "$delay_single_quote_subst"`' -postdeps_CXX='`$ECHO "X$postdeps_CXX" | $Xsed -e "$delay_single_quote_subst"`' -compiler_lib_search_path_CXX='`$ECHO "X$compiler_lib_search_path_CXX" | $Xsed -e "$delay_single_quote_subst"`' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' +predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' +postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' +predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' +postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' +LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' +reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' +reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' +GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' +inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' +link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' +always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' +exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' +predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' +postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' +predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' +postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + # Quote evaled strings. -for var in SED \ +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ GREP \ EGREP \ FGREP \ @@ -16639,10 +17646,16 @@ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ +OBJDUMP \ deplibs_check_method \ file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ +archiver_list_spec \ STRIP \ RANLIB \ CC \ @@ -16652,14 +17665,14 @@ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ -SHELL \ -ECHO \ +nm_file_list_spec \ lt_prog_compiler_no_builtin_flag \ -lt_prog_compiler_wl \ lt_prog_compiler_pic \ +lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ +MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ @@ -16673,9 +17686,7 @@ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ -hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ -fix_srcfile_path \ exclude_expsyms \ include_expsyms \ file_list_spec \ @@ -16683,6 +17694,7 @@ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ +install_override_mode \ finish_eval \ old_striplib \ striplib \ @@ -16693,10 +17705,11 @@ predeps \ postdeps \ compiler_lib_search_path \ LD_CXX \ +reload_flag_CXX \ compiler_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ -lt_prog_compiler_wl_CXX \ lt_prog_compiler_pic_CXX \ +lt_prog_compiler_wl_CXX \ lt_prog_compiler_static_CXX \ lt_cv_prog_compiler_c_o_CXX \ export_dynamic_flag_spec_CXX \ @@ -16706,9 +17719,7 @@ with_gnu_ld_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ hardcode_libdir_flag_spec_CXX \ -hardcode_libdir_flag_spec_ld_CXX \ hardcode_libdir_separator_CXX \ -fix_srcfile_path_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX \ file_list_spec_CXX \ @@ -16718,9 +17729,9 @@ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX; do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -16742,11 +17753,13 @@ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ +postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec \ +reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ @@ -16755,10 +17768,11 @@ archive_expsym_cmds_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ export_symbols_cmds_CXX \ -prelink_cmds_CXX; do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in +prelink_cmds_CXX \ +postlink_cmds_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -16766,12 +17780,6 @@ prelink_cmds_CXX; do esac done -# Fix-up fallback echo if it was mangled by the above quoting rules. -case \$lt_ECHO in -*'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` - ;; -esac - ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' @@ -17520,7 +18528,8 @@ $as_echo X"$file" | # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. @@ -17568,6 +18577,15 @@ pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + # The host system. host_alias=$host_alias host=$host @@ -17617,20 +18635,42 @@ SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method -# Command to use when deplibs_check_method == "file_magic". +# Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + # The archiver. AR=$lt_AR + +# Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + # A symbol stripping program. STRIP=$lt_STRIP @@ -17639,6 +18679,9 @@ RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + # A C compiler. LTCC=$lt_CC @@ -17657,14 +18700,14 @@ global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix -# The name of the directory that contains temporary libtool files. -objdir=$objdir +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL +# The root where to search for dependent libraries,and in which our libraries should be installed. +lt_sysroot=$lt_sysroot -# An echo program that does not interpret backslashes. -ECHO=$lt_ECHO +# The name of the directory that contains temporary libtool files. +objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD @@ -17672,6 +18715,9 @@ MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL @@ -17728,6 +18774,9 @@ library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds @@ -17767,6 +18816,10 @@ striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds @@ -17779,12 +18832,12 @@ with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl - # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static @@ -17834,10 +18887,6 @@ no_undefined_flag=$lt_no_undefined_flag # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec -# If ld is used when linking, flag to hardcode \$libdir into a binary -# during linking. This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld - # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator @@ -17871,9 +18920,6 @@ inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path=$lt_fix_srcfile_path - # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols @@ -17889,6 +18935,9 @@ include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + # Specify filename containing input files. file_list_spec=$lt_file_list_spec @@ -17935,212 +18984,169 @@ ltmain="$ac_aux_dir/ltmain.sh" # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? - sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - case $xsi_shell in - yes) - cat << \_LT_EOF >> "$cfgfile" - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac -} - -# func_basename file -func_basename () -{ - func_basename_result="${1##*/}" -} - -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () -{ - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac - func_basename_result="${1##*/}" -} - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -func_stripname () -{ - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary parameter first. - func_stripname_result=${3} - func_stripname_result=${func_stripname_result#"${1}"} - func_stripname_result=${func_stripname_result%"${2}"} -} - -# func_opt_split -func_opt_split () -{ - func_opt_split_opt=${1%%=*} - func_opt_split_arg=${1#*=} -} - -# func_lo2o object -func_lo2o () -{ - case ${1} in - *.lo) func_lo2o_result=${1%.lo}.${objext} ;; - *) func_lo2o_result=${1} ;; - esac -} - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=${1%.*}.lo -} - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=$(( $* )) -} - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=${#1} -} - -_LT_EOF - ;; - *) # Bourne compatible functions. - cat << \_LT_EOF >> "$cfgfile" - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} - -# func_basename file -func_basename () -{ - func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` -} - - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; - esac -} - -# sed scripts: -my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' -my_sed_long_arg='1s/^-[^=]*=//' - -# func_opt_split -func_opt_split () -{ - func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` - func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` -} - -# func_lo2o object -func_lo2o () -{ - func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` -} - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` -} - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=`expr "$@"` -} - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` -} - -_LT_EOF -esac - -case $lt_shell_append in - yes) - cat << \_LT_EOF >> "$cfgfile" - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "$1+=\$2" -} -_LT_EOF - ;; - *) - cat << \_LT_EOF >> "$cfgfile" - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "$1=\$$1\$2" -} - -_LT_EOF - ;; - esac - - - sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + if test x"$xsi_shell" = xyes; then + sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ +func_dirname ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_basename ()$/,/^} # func_basename /c\ +func_basename ()\ +{\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ +func_dirname_and_basename ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ +func_stripname ()\ +{\ +\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ +\ # positional parameters, so assign one to ordinary parameter first.\ +\ func_stripname_result=${3}\ +\ func_stripname_result=${func_stripname_result#"${1}"}\ +\ func_stripname_result=${func_stripname_result%"${2}"}\ +} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ +func_split_long_opt ()\ +{\ +\ func_split_long_opt_name=${1%%=*}\ +\ func_split_long_opt_arg=${1#*=}\ +} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ +func_split_short_opt ()\ +{\ +\ func_split_short_opt_arg=${1#??}\ +\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ +} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ +func_lo2o ()\ +{\ +\ case ${1} in\ +\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ +\ *) func_lo2o_result=${1} ;;\ +\ esac\ +} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_xform ()$/,/^} # func_xform /c\ +func_xform ()\ +{\ + func_xform_result=${1%.*}.lo\ +} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_arith ()$/,/^} # func_arith /c\ +func_arith ()\ +{\ + func_arith_result=$(( $* ))\ +} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_len ()$/,/^} # func_len /c\ +func_len ()\ +{\ + func_len_result=${#1}\ +} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + +fi + +if test x"$lt_shell_append" = xyes; then + sed -e '/^func_append ()$/,/^} # func_append /c\ +func_append ()\ +{\ + eval "${1}+=\\${2}"\ +} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ +func_append_quoted ()\ +{\ +\ func_quote_for_eval "${2}"\ +\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ +} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 +$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} +fi + + + mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" @@ -18152,6 +19158,10 @@ _LT_EOF # The linker used to build libraries. LD=$lt_LD_CXX +# How to create reloadable object files. +reload_flag=$lt_reload_flag_CXX +reload_cmds=$lt_reload_cmds_CXX + # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_CXX @@ -18164,12 +19174,12 @@ with_gcc=$GCC_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_CXX - # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX @@ -18219,10 +19229,6 @@ no_undefined_flag=$lt_no_undefined_flag_CXX # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX -# If ld is used when linking, flag to hardcode \$libdir into a binary -# during linking. This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX - # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX @@ -18256,9 +19262,6 @@ inherit_rpath=$inherit_rpath_CXX # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path=$lt_fix_srcfile_path_CXX - # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_CXX @@ -18274,6 +19277,9 @@ include_expsyms=$lt_include_expsyms_CXX # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_CXX +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds_CXX + # Specify filename containing input files. file_list_spec=$lt_file_list_spec_CXX diff --git a/configure.ac b/configure.ac index 63322b4..bc496c9 100644 --- a/configure.ac +++ b/configure.ac @@ -12,8 +12,9 @@ AC_PREREQ(2.59) # In the SVN trunk, the version should always be the next anticipated release # version with the "-pre" suffix. (We used to use "-SNAPSHOT" but this pushed # the size of one file name in the dist tarfile over the 99-char limit.) -AC_INIT([Protocol Buffers],[2.3.0],[protobuf@googlegroups.com],[protobuf]) +AC_INIT([Protocol Buffers],[2.6.0],[protobuf@googlegroups.com],[protobuf]) +AM_MAINTAINER_MODE([enable]) AC_CONFIG_SRCDIR(src/google/protobuf/message.cc) AC_CONFIG_HEADERS([config.h]) @@ -28,7 +29,7 @@ AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"], AC_CANONICAL_TARGET -AM_INIT_AUTOMAKE +AM_INIT_AUTOMAKE([subdir-objects]) AC_ARG_WITH([zlib], [AS_HELP_STRING([--with-zlib], @@ -89,12 +90,12 @@ AS_IF([test "$with_zlib" != no], [ # First check the zlib header version. AC_COMPILE_IFELSE( - AC_LANG_PROGRAM([[ + [AC_LANG_PROGRAM([[ #include #if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204) # error zlib version too old #endif - ]], []), [ + ]], [])], [ AC_MSG_RESULT([ok (1.2.0.4 or later)]) # Also need to add -lz to the linker flags and make sure this succeeds. @@ -118,7 +119,7 @@ AM_CONDITIONAL([HAVE_ZLIB], [test $HAVE_ZLIB = 1]) AS_IF([test "$with_protoc" != "no"], [ PROTOC=$with_protoc - AS_IF([test "$with_protoc" == "yes"], [ + AS_IF([test "$with_protoc" = "yes"], [ # No argument given. Use system protoc. PROTOC=protoc ]) diff --git a/depcomp b/depcomp index e5f9736..bd0ac08 100755 --- a/depcomp +++ b/depcomp @@ -1,10 +1,10 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2007-03-29.01 +scriptversion=2011-12-04.11; # UTC -# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software -# Foundation, Inc. +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010, +# 2011 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,9 +17,7 @@ scriptversion=2007-03-29.01 # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -46,7 +44,7 @@ Environment variables: object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. - tmpdepfile Temporary file to use when outputing dependencies. + tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . @@ -87,6 +85,23 @@ if test "$depmode" = dashXmstdout; then depmode=dashmstdout fi +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what @@ -151,10 +166,12 @@ gcc) ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as -## well. +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; @@ -192,14 +209,14 @@ sgi) ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' -' ' ' >> $depfile - echo >> $depfile +' ' ' >> "$depfile" + echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> $depfile + >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile @@ -328,7 +345,12 @@ hp2) if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add `dependent.h:' lines. - sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi @@ -393,6 +415,52 @@ tru64) rm -f "$tmpdepfile" ;; +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test "$stat" = 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/ \1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/ / + G + p +}' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. @@ -404,7 +472,7 @@ dashmstdout) # Remove the call to Libtool. if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do + while test "X$1" != 'X--mode=compile'; do shift done shift @@ -455,36 +523,45 @@ makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do + while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift - cleared=no - for arg in "$@"; do + cleared=no eat=no + for arg + do case $cleared in no) set ""; shift cleared=yes ;; esac + if test $eat = yes; then + eat=no + continue + fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done - obj_suffix="`echo $object | sed 's/^.*\././'`" + obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation @@ -500,7 +577,7 @@ cpp) # Remove the call to Libtool. if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do + while test "X$1" != 'X--mode=compile'; do shift done shift @@ -538,13 +615,27 @@ cpp) msvisualcpp) # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. + # always write the preprocessed file to stdout. "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + IFS=" " for arg do case "$arg" in + -o) + shift + ;; + $object) + shift + ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift @@ -557,16 +648,23 @@ msvisualcpp) ;; esac done - "$@" -E | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + none) exec "$@" ;; @@ -585,5 +683,6 @@ exit 0 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" # End: diff --git a/editors/proto.vim b/editors/proto.vim index 42f3307..2a25fa6 100644 --- a/editors/proto.vim +++ b/editors/proto.vim @@ -69,11 +69,10 @@ syn keyword pbBool true false syn match pbInt /-\?\<\d\+\>/ syn match pbInt /\<0[xX]\x+\>/ syn match pbFloat /\<-\?\d*\(\.\d*\)\?/ -" TODO: .proto also supports C-style block comments; -" see /usr/share/vim/vim70/syntax/c.vim for how it's done. +syn region pbComment start="\/\*" end="\*\/" contains=@pbCommentGrp syn region pbComment start="//" skip="\\$" end="$" keepend contains=@pbCommentGrp -syn region pbString start=/"/ skip=/\\"/ end=/"/ -syn region pbString start=/'/ skip=/\\'/ end=/'/ +syn region pbString start=/"/ skip=/\\./ end=/"/ +syn region pbString start=/'/ skip=/\\./ end=/'/ if version >= 508 || !exists("did_proto_syn_inits") if version < 508 diff --git a/examples/AddPerson.java b/examples/AddPerson.java index 4917684..ca5ac27 100644 --- a/examples/AddPerson.java +++ b/examples/AddPerson.java @@ -70,8 +70,11 @@ class AddPerson { // Read the existing address book. try { FileInputStream input = new FileInputStream(args[0]); - addressBook.mergeFrom(input); - input.close(); + try { + addressBook.mergeFrom(input); + } finally { + try { input.close(); } catch (Throwable ignore) {} + } } catch (FileNotFoundException e) { System.out.println(args[0] + ": File not found. Creating a new file."); } @@ -83,7 +86,10 @@ class AddPerson { // Write the new address book back to disk. FileOutputStream output = new FileOutputStream(args[0]); - addressBook.build().writeTo(output); - output.close(); + try { + addressBook.build().writeTo(output); + } finally { + output.close(); + } } } diff --git a/examples/list_people.cc b/examples/list_people.cc index 5363152..d0f40d6 100644 --- a/examples/list_people.cc +++ b/examples/list_people.cc @@ -4,6 +4,7 @@ #include #include #include "addressbook.pb.h" +#include using namespace std; // Iterates though all people in the AddressBook and prints info about them. diff --git a/gtest/build-aux/config.guess b/gtest/build-aux/config.guess index 278f9e9..d622a44 100755 --- a/gtest/build-aux/config.guess +++ b/gtest/build-aux/config.guess @@ -1,10 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. -timestamp='2007-07-22' +timestamp='2012-02-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -17,9 +17,7 @@ timestamp='2007-07-22' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -27,16 +25,16 @@ timestamp='2007-07-22' # the same distribution terms that you use for the rest of that program. -# Originally written by Per Bothner . -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` @@ -56,7 +54,8 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -144,7 +143,7 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward @@ -170,7 +169,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null + | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? @@ -180,7 +179,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in fi ;; *) - os=netbsd + os=netbsd ;; esac # The OS release @@ -223,7 +222,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on @@ -269,7 +268,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit ;; + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead @@ -295,7 +297,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo s390-ibm-zvmoe exit ;; *:OS400:*:*) - echo powerpc-ibm-os400 + echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} @@ -324,14 +326,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize @@ -375,23 +396,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} - exit ;; + exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; @@ -461,8 +482,8 @@ EOF echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ @@ -475,7 +496,7 @@ EOF else echo i586-dg-dgux${UNAME_RELEASE} fi - exit ;; + exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; @@ -532,7 +553,7 @@ EOF echo rs6000-ibm-aix3.2 fi exit ;; - *:AIX:*:[45]) + *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 @@ -575,52 +596,52 @@ EOF 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac + esac ;; + esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + sed 's/^ //' << EOF >$dummy.c - #define _HPUX_SOURCE - #include - #include + #define _HPUX_SOURCE + #include + #include - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa @@ -640,7 +661,7 @@ EOF # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep __LP64__ >/dev/null + grep -q __LP64__ then HP_ARCH="hppa2.0w" else @@ -711,22 +732,22 @@ EOF exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit ;; + exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit ;; + exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit ;; + exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit ;; + exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit ;; + exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; @@ -750,14 +771,14 @@ EOF exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} @@ -769,13 +790,12 @@ EOF echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) - case ${UNAME_MACHINE} in - pc98) - echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) @@ -784,25 +804,34 @@ EOF *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; - *:Interix*:[3456]*) - case ${UNAME_MACHINE} in + *:Interix*:*) + case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; - EM64T | authenticamd) + authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we @@ -832,20 +861,68 @@ EOF i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; - arm*:Linux:*:*) + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) - echo cris-axis-linux-gnu + echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; crisv32:Linux:*:*) - echo crisv32-axis-linux-gnu + echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; frv:Linux:*:*) - echo frv-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu @@ -856,74 +933,33 @@ EOF m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - mips:Linux:*:*) + mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU - #undef mips - #undef mipsel + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mipsel + CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips + CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips64 - #undef mips64el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mips64el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips64 - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) - echo or32-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu + padre:Linux:*:*) + echo sparc-unknown-linux-gnu exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level @@ -933,14 +969,17 @@ EOF *) echo hppa-unknown-linux-gnu ;; esac exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu @@ -948,78 +987,18 @@ EOF sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - xtensa:Linux:*:*) - echo xtensa-unknown-linux-gnu + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - # Set LC_ALL=C to ensure ld outputs messages in English. - ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit ;; - esac - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif - #else - #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) - LIBC=gnu - #else - LIBC=gnuaout - #endif - #endif - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^LIBC/{ - s: ::g - p - }'`" - test x"${LIBC}" != x && { - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit - } - test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } - ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both @@ -1027,11 +1006,11 @@ EOF echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. + # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) @@ -1048,7 +1027,7 @@ EOF i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) @@ -1063,7 +1042,7 @@ EOF fi exit ;; i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. + # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; @@ -1091,10 +1070,13 @@ EOF exit ;; pc:*:*:*) # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit ;; + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; @@ -1129,8 +1111,18 @@ EOF /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; @@ -1143,7 +1135,7 @@ EOF rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) @@ -1163,10 +1155,10 @@ EOF echo ns32k-sni-sysv fi exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm @@ -1192,11 +1184,11 @@ EOF exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv${UNAME_RELEASE} else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv${UNAME_RELEASE} fi - exit ;; + exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; @@ -1206,6 +1198,9 @@ EOF BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; @@ -1233,6 +1228,16 @@ EOF *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} @@ -1248,6 +1253,9 @@ EOF *:QNX:*:4*) echo i386-pc-qnx exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; @@ -1293,13 +1301,13 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` + UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; @@ -1314,6 +1322,12 @@ EOF i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 @@ -1336,11 +1350,11 @@ main () #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 - "4" + "4" #else - "" + "" #endif - ); exit (0); + ); exit (0); #endif #endif @@ -1474,9 +1488,9 @@ This script, last modified $timestamp, has failed to recognize the operating system you are using. It is advised that you download the most up to date version of the config scripts from - http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD and - http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD If the version you run ($0) is already up to date, please send the following data and any information you think might be diff --git a/gtest/build-aux/config.sub b/gtest/build-aux/config.sub index 1761d8b..c894da4 100755 --- a/gtest/build-aux/config.sub +++ b/gtest/build-aux/config.sub @@ -1,10 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. -timestamp='2007-06-28' +timestamp='2012-02-10' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -21,9 +21,7 @@ timestamp='2007-06-28' # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -32,13 +30,16 @@ timestamp='2007-06-28' # Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. +# diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. @@ -72,7 +73,8 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -120,12 +122,18 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ - uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] @@ -148,10 +156,13 @@ case $os in -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray) + -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; + -bluegene*) + os=-cnk + ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 @@ -166,10 +177,10 @@ case $os in os=-chorusos basic_machine=$1 ;; - -chorusrdb) - os=-chorusrdb + -chorusrdb) + os=-chorusrdb basic_machine=$1 - ;; + ;; -hiux*) os=-hiuxwe2 ;; @@ -238,24 +249,32 @@ case $basic_machine in # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ + | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ + | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep \ + | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ - | mips64vr | mips64vrel \ + | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ @@ -268,29 +287,42 @@ case $basic_machine in | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | moxie \ | mt \ | msp430 \ + | nds32 | nds32le | nds32be \ | nios | nios2 \ | ns16k | ns32k \ + | open8 \ | or32 \ | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ + | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu | strongarm \ - | tahoe | thumb | tic4x | tic80 | tron \ - | v850 | v850e \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ - | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ - | z8k) + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) basic_machine=$basic_machine-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; @@ -300,6 +332,21 @@ case $basic_machine in basic_machine=mt-unknown ;; + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. @@ -314,29 +361,36 @@ case $basic_machine in # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ + | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ + | be32-* | be64-* \ | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ + | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ @@ -351,27 +405,36 @@ case $basic_machine in | mmix-* \ | mt-* \ | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ - | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ | tron-* \ - | v850-* | v850e-* | vax-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ - | xstormy16-* | xtensa-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ | ymp-* \ - | z8k-*) + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. @@ -389,7 +452,7 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; - abacus) + abacus) basic_machine=abacus-unknown ;; adobe68k) @@ -435,6 +498,10 @@ case $basic_machine in basic_machine=m68k-apollo os=-bsd ;; + aros) + basic_machine=i386-pc + os=-aros + ;; aux) basic_machine=m68k-apple os=-aux @@ -443,10 +510,35 @@ case $basic_machine in basic_machine=ns32k-sequent os=-dynix ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; c90) basic_machine=c90-cray os=-unicos ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; convex-c1) basic_machine=c1-convex os=-bsd @@ -475,7 +567,7 @@ case $basic_machine in basic_machine=craynv-cray os=-unicosmp ;; - cr16) + cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; @@ -514,6 +606,10 @@ case $basic_machine in basic_machine=m88k-motorola os=-sysv3 ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp @@ -629,7 +725,6 @@ case $basic_machine in i370-ibm* | ibm*) basic_machine=i370-ibm ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 @@ -668,6 +763,14 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; m88k-omron*) basic_machine=m88k-omron ;; @@ -679,6 +782,9 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; + microblaze) + basic_machine=microblaze-xilinx + ;; mingw32) basic_machine=i386-pc os=-mingw32 @@ -715,10 +821,18 @@ case $basic_machine in ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; + msys) + basic_machine=i386-pc + os=-msys + ;; mvs) basic_machine=i370-ibm os=-mvs ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; ncr3000) basic_machine=i486-ncr os=-sysv4 @@ -783,6 +897,12 @@ case $basic_machine in np1) basic_machine=np1-gould ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -813,6 +933,14 @@ case $basic_machine in basic_machine=i860-intel os=-osf ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; pbd) basic_machine=sparc-tti ;; @@ -857,9 +985,10 @@ case $basic_machine in ;; power) basic_machine=power-ibm ;; - ppc) basic_machine=powerpc-unknown + ppc | ppcbe) basic_machine=powerpc-unknown ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown @@ -953,6 +1082,9 @@ case $basic_machine in basic_machine=i860-stratus os=-sysv4 ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; sun2) basic_machine=m68000-sun ;; @@ -1009,17 +1141,9 @@ case $basic_machine in basic_machine=t90-cray os=-unicos ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tic55x | c55x*) - basic_machine=tic55x-unknown - os=-coff - ;; - tic6x | c6x*) - basic_machine=tic6x-unknown - os=-coff + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown @@ -1088,6 +1212,9 @@ case $basic_machine in xps | xps100) basic_machine=xps100-honeywell ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; ymp) basic_machine=ymp-cray os=-unicos @@ -1096,6 +1223,10 @@ case $basic_machine in basic_machine=z8k-unknown os=-sim ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; none) basic_machine=none-none os=-none @@ -1134,7 +1265,7 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) @@ -1181,9 +1312,12 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases + # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; @@ -1204,10 +1338,11 @@ case $os in # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ + | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ @@ -1216,9 +1351,10 @@ case $os in | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ @@ -1226,7 +1362,7 @@ case $os in | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1265,7 +1401,7 @@ case $os in -opened*) os=-openedition ;; - -os400*) + -os400*) os=-os400 ;; -wince*) @@ -1314,7 +1450,7 @@ case $os in -sinix*) os=-sysv4 ;; - -tpf*) + -tpf*) os=-tpf ;; -triton*) @@ -1356,6 +1492,11 @@ case $os in -zvmoe) os=-zvmoe ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; -none) ;; *) @@ -1378,10 +1519,10 @@ else # system, and we'll never get to this point. case $basic_machine in - score-*) + score-*) os=-elf ;; - spu-*) + spu-*) os=-elf ;; *-acorn) @@ -1393,8 +1534,17 @@ case $basic_machine in arm*-semi) os=-aout ;; - c4x-* | tic4x-*) - os=-coff + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff ;; # This must come before the *-dec entry. pdp10-*) @@ -1414,14 +1564,11 @@ case $basic_machine in ;; m68000-sun) os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 ;; m68*-cisco) os=-aout ;; - mep-*) + mep-*) os=-elf ;; mips*-cisco) @@ -1448,7 +1595,7 @@ case $basic_machine in *-ibm) os=-aix ;; - *-knuth) + *-knuth) os=-mmixware ;; *-wec) @@ -1553,7 +1700,7 @@ case $basic_machine in -sunos*) vendor=sun ;; - -aix*) + -cnk*|-aix*) vendor=ibm ;; -beos*) diff --git a/gtest/build-aux/depcomp b/gtest/build-aux/depcomp index e5f9736..bd0ac08 100755 --- a/gtest/build-aux/depcomp +++ b/gtest/build-aux/depcomp @@ -1,10 +1,10 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2007-03-29.01 +scriptversion=2011-12-04.11; # UTC -# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software -# Foundation, Inc. +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010, +# 2011 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,9 +17,7 @@ scriptversion=2007-03-29.01 # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -46,7 +44,7 @@ Environment variables: object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. - tmpdepfile Temporary file to use when outputing dependencies. + tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . @@ -87,6 +85,23 @@ if test "$depmode" = dashXmstdout; then depmode=dashmstdout fi +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what @@ -151,10 +166,12 @@ gcc) ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as -## well. +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; @@ -192,14 +209,14 @@ sgi) ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' -' ' ' >> $depfile - echo >> $depfile +' ' ' >> "$depfile" + echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> $depfile + >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile @@ -328,7 +345,12 @@ hp2) if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add `dependent.h:' lines. - sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi @@ -393,6 +415,52 @@ tru64) rm -f "$tmpdepfile" ;; +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test "$stat" = 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/ \1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/ / + G + p +}' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. @@ -404,7 +472,7 @@ dashmstdout) # Remove the call to Libtool. if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do + while test "X$1" != 'X--mode=compile'; do shift done shift @@ -455,36 +523,45 @@ makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do + while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift - cleared=no - for arg in "$@"; do + cleared=no eat=no + for arg + do case $cleared in no) set ""; shift cleared=yes ;; esac + if test $eat = yes; then + eat=no + continue + fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done - obj_suffix="`echo $object | sed 's/^.*\././'`" + obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation @@ -500,7 +577,7 @@ cpp) # Remove the call to Libtool. if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do + while test "X$1" != 'X--mode=compile'; do shift done shift @@ -538,13 +615,27 @@ cpp) msvisualcpp) # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. + # always write the preprocessed file to stdout. "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + IFS=" " for arg do case "$arg" in + -o) + shift + ;; + $object) + shift + ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift @@ -557,16 +648,23 @@ msvisualcpp) ;; esac done - "$@" -E | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + none) exec "$@" ;; @@ -585,5 +683,6 @@ exit 0 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" # End: diff --git a/gtest/build-aux/install-sh b/gtest/build-aux/install-sh index a5897de..a9244eb 100755 --- a/gtest/build-aux/install-sh +++ b/gtest/build-aux/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2006-12-25.00 +scriptversion=2011-01-19.21; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -156,6 +156,10 @@ while test $# -ne 0; do -s) stripcmd=$stripprog;; -t) dst_arg=$2 + # Protect names problematic for `test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac shift;; -T) no_target_directory=true;; @@ -186,6 +190,10 @@ if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then fi shift # arg dst_arg=$arg + # Protect names problematic for `test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac done fi @@ -200,7 +208,11 @@ if test $# -eq 0; then fi if test -z "$dir_arg"; then - trap '(exit $?); exit' 1 2 13 15 + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. @@ -228,9 +240,9 @@ fi for src do - # Protect names starting with `-'. + # Protect names problematic for `test' and other utilities. case $src in - -*) src=./$src;; + -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then @@ -252,12 +264,7 @@ do echo "$0: no destination specified." >&2 exit 1 fi - dst=$dst_arg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst;; - esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. @@ -385,7 +392,7 @@ do case $dstdir in /*) prefix='/';; - -*) prefix='./';; + [-=\(\)!]*) prefix='./';; *) prefix='';; esac @@ -403,7 +410,7 @@ do for d do - test -z "$d" && continue + test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then @@ -515,5 +522,6 @@ done # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" # End: diff --git a/gtest/build-aux/missing b/gtest/build-aux/missing index 1c8ff70..86a8fc3 100755 --- a/gtest/build-aux/missing +++ b/gtest/build-aux/missing @@ -1,10 +1,10 @@ #! /bin/sh # Common stub for a few missing GNU programs while installing. -scriptversion=2006-05-10.23 +scriptversion=2012-01-06.13; # UTC -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 -# Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, +# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify @@ -18,9 +18,7 @@ scriptversion=2006-05-10.23 # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -86,9 +84,11 @@ Supported PROGRAM values: help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] +Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and +\`g' are ignored when checking the name. + Send bug reports to ." exit $? ;; @@ -106,23 +106,21 @@ Send bug reports to ." esac +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect -# the program). +# the program). This is about non-GNU programs, so use $1 not +# $program. case $1 in - lex|yacc) + lex*|yacc*) # Not GNU programs, they don't have --version. ;; - tar) - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - exit 1 - fi - ;; - *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. @@ -138,7 +136,7 @@ esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. -case $1 in +case $program in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if @@ -148,7 +146,7 @@ WARNING: \`$1' is $msg. You should only need it if touch aclocal.m4 ;; - autoconf) + autoconf*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the @@ -157,7 +155,7 @@ WARNING: \`$1' is $msg. You should only need it if touch configure ;; - autoheader) + autoheader*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want @@ -187,7 +185,7 @@ WARNING: \`$1' is $msg. You should only need it if while read f; do touch "$f"; done ;; - autom4te) + autom4te*) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the @@ -210,7 +208,7 @@ WARNING: \`$1' is needed, but is $msg. fi ;; - bison|yacc) + bison*|yacc*) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package @@ -218,7 +216,7 @@ WARNING: \`$1' $msg. You should only need it if \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then - eval LASTARG="\${$#}" + eval LASTARG=\${$#} case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` @@ -240,7 +238,7 @@ WARNING: \`$1' $msg. You should only need it if fi ;; - lex|flex) + lex*|flex*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package @@ -248,7 +246,7 @@ WARNING: \`$1' is $msg. You should only need it if \`Flex' from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then - eval LASTARG="\${$#}" + eval LASTARG=\${$#} case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` @@ -263,7 +261,7 @@ WARNING: \`$1' is $msg. You should only need it if fi ;; - help2man) + help2man*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the @@ -277,11 +275,11 @@ WARNING: \`$1' is $msg. You should only need it if else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" - exit 1 + exit $? fi ;; - makeinfo) + makeinfo*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file @@ -310,41 +308,6 @@ WARNING: \`$1' is $msg. You should only need it if touch $file ;; - tar) - shift - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case $firstarg in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case $firstarg in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. @@ -363,5 +326,6 @@ exit 0 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" # End: diff --git a/install-sh b/install-sh index a5897de..a9244eb 100755 --- a/install-sh +++ b/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2006-12-25.00 +scriptversion=2011-01-19.21; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -156,6 +156,10 @@ while test $# -ne 0; do -s) stripcmd=$stripprog;; -t) dst_arg=$2 + # Protect names problematic for `test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac shift;; -T) no_target_directory=true;; @@ -186,6 +190,10 @@ if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then fi shift # arg dst_arg=$arg + # Protect names problematic for `test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac done fi @@ -200,7 +208,11 @@ if test $# -eq 0; then fi if test -z "$dir_arg"; then - trap '(exit $?); exit' 1 2 13 15 + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. @@ -228,9 +240,9 @@ fi for src do - # Protect names starting with `-'. + # Protect names problematic for `test' and other utilities. case $src in - -*) src=./$src;; + -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then @@ -252,12 +264,7 @@ do echo "$0: no destination specified." >&2 exit 1 fi - dst=$dst_arg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst;; - esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. @@ -385,7 +392,7 @@ do case $dstdir in /*) prefix='/';; - -*) prefix='./';; + [-=\(\)!]*) prefix='./';; *) prefix='';; esac @@ -403,7 +410,7 @@ do for d do - test -z "$d" && continue + test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then @@ -515,5 +522,6 @@ done # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" # End: diff --git a/java/README.txt b/java/README.txt index 4dfef14..f516078 100644 --- a/java/README.txt +++ b/java/README.txt @@ -101,7 +101,7 @@ extensions. To create a jar file for the runtime and run tests invoke "mvn package -P micro" from the /java directory. The generated jar file is -java/target/protobuf-java-2.2.0-micro.jar. +java/target/protobuf-java-2.6.0-micro.jar. If you wish to compile the MICRO_RUNTIME your self, place the 7 files below, in /com/google/protobuf and @@ -621,7 +621,7 @@ To use nano protobufs within the Android repo: To use nano protobufs outside of Android repo: - Link with the generated jar file - java/target/protobuf-java-2.3.0-nano.jar. + java/target/protobuf-java-2.6.0-nano.jar. - Invoke with --javanano_out, e.g.: ./protoc '--javanano_out=\ @@ -643,7 +643,7 @@ Please run the following steps to test: - cd ../../.. - . build/envsetup.sh - lunch 1 -- "make -j12 aprotoc libprotobuf-java-2.3.0-nano aprotoc-test-nano-params NanoAndroidTest" and +- "make -j12 aprotoc libprotobuf-java-nano aprotoc-test-nano-params NanoAndroidTest" and check for build errors. - Plug in an Android device or start an emulator. - adb install -r out/target/product/generic/data/app/NanoAndroidTest.apk diff --git a/java/pom.xml b/java/pom.xml index 6c7191c..b7b690f 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -10,7 +10,7 @@ com.google.protobuf protobuf-java - 2.3.0 + 2.6.0 jar Protocol Buffer Java API @@ -96,23 +96,37 @@ - - + + + + + + + + + + + + + + + + @@ -219,8 +233,6 @@ target/generated-test-sources - - run @@ -228,6 +240,18 @@ + + org.apache.felix + maven-bundle-plugin + true + + + http://code.google.com/p/protobuf + com.google.protobuf + com.google.protobuf;version=2.6.0 + + + @@ -246,11 +270,25 @@ **/ExtensionRegistryLite.java **/FieldSet.java **/GeneratedMessageLite.java - **/InvalidProtocolBufferException.java **/Internal.java + **/InvalidProtocolBufferException.java + **/LazyStringArrayList.java + **/LazyStringList.java **/MessageLite.java + **/MessageLiteOrBuilder.java + **/SmallSortedMap.java **/UninitializedMessageException.java + **/UnmodifiableLazyStringList.java **/WireFormat.java + **/Parser.java + **/AbstractParser.java + **/BoundedByteString.java + **/LiteralByteString.java + **/RopeByteString.java + **/Utf8.java + **/LazyField.java + **/LazyFieldLite.java + **/ProtocolStringList.java **/LiteTest.java diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java index b059bc9..a645c20 100644 --- a/java/src/main/java/com/google/protobuf/AbstractMessage.java +++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java @@ -30,12 +30,13 @@ package com.google.protobuf; -import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.OneofDescriptor; +import com.google.protobuf.Internal.EnumLite; -import java.io.InputStream; import java.io.IOException; -import java.util.ArrayList; +import java.io.InputStream; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -47,37 +48,30 @@ import java.util.Map; */ public abstract class AbstractMessage extends AbstractMessageLite implements Message { - @SuppressWarnings("unchecked") public boolean isInitialized() { - // Check that all required fields are present. - for (final FieldDescriptor field : getDescriptorForType().getFields()) { - if (field.isRequired()) { - if (!hasField(field)) { - return false; - } - } - } + return MessageReflection.isInitialized(this); + } - // Check that embedded messages are initialized. - for (final Map.Entry entry : - getAllFields().entrySet()) { - final FieldDescriptor field = entry.getKey(); - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - if (field.isRepeated()) { - for (final Message element : (List) entry.getValue()) { - if (!element.isInitialized()) { - return false; - } - } - } else { - if (!((Message) entry.getValue()).isInitialized()) { - return false; - } - } - } - } - return true; + public List findInitializationErrors() { + return MessageReflection.findMissingFields(this); + } + + public String getInitializationErrorString() { + return MessageReflection.delimitWithCommas(findInitializationErrors()); + } + + /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ + @Override + public boolean hasOneof(OneofDescriptor oneof) { + throw new UnsupportedOperationException("hasOneof() is not implemented."); + } + + /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ + @Override + public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) { + throw new UnsupportedOperationException( + "getOneofFieldDescriptor() is not implemented."); } @Override @@ -86,28 +80,7 @@ public abstract class AbstractMessage extends AbstractMessageLite } public void writeTo(final CodedOutputStream output) throws IOException { - final boolean isMessageSet = - getDescriptorForType().getOptions().getMessageSetWireFormat(); - - for (final Map.Entry entry : - getAllFields().entrySet()) { - final FieldDescriptor field = entry.getKey(); - final Object value = entry.getValue(); - if (isMessageSet && field.isExtension() && - field.getType() == FieldDescriptor.Type.MESSAGE && - !field.isRepeated()) { - output.writeMessageSetExtension(field.getNumber(), (Message) value); - } else { - FieldSet.writeField(field, value, output); - } - } - - final UnknownFieldSet unknownFields = getUnknownFields(); - if (isMessageSet) { - unknownFields.writeAsMessageSetTo(output); - } else { - unknownFields.writeTo(output); - } + MessageReflection.writeMessageTo(this, output, false); } private int memoizedSize = -1; @@ -118,33 +91,8 @@ public abstract class AbstractMessage extends AbstractMessageLite return size; } - size = 0; - final boolean isMessageSet = - getDescriptorForType().getOptions().getMessageSetWireFormat(); - - for (final Map.Entry entry : - getAllFields().entrySet()) { - final FieldDescriptor field = entry.getKey(); - final Object value = entry.getValue(); - if (isMessageSet && field.isExtension() && - field.getType() == FieldDescriptor.Type.MESSAGE && - !field.isRepeated()) { - size += CodedOutputStream.computeMessageSetExtensionSize( - field.getNumber(), (Message) value); - } else { - size += FieldSet.computeFieldSize(field, value); - } - } - - final UnknownFieldSet unknownFields = getUnknownFields(); - if (isMessageSet) { - size += unknownFields.getSerializedSizeAsMessageSet(); - } else { - size += unknownFields.getSerializedSize(); - } - - memoizedSize = size; - return size; + memoizedSize = MessageReflection.getSerializedSize(this); + return memoizedSize; } @Override @@ -159,18 +107,117 @@ public abstract class AbstractMessage extends AbstractMessageLite if (getDescriptorForType() != otherMessage.getDescriptorForType()) { return false; } - return getAllFields().equals(otherMessage.getAllFields()) && + return compareFields(getAllFields(), otherMessage.getAllFields()) && getUnknownFields().equals(otherMessage.getUnknownFields()); } @Override public int hashCode() { - int hash = 41; - hash = (19 * hash) + getDescriptorForType().hashCode(); - hash = (53 * hash) + getAllFields().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); + int hash = memoizedHashCode; + if (hash == 0) { + hash = 41; + hash = (19 * hash) + getDescriptorForType().hashCode(); + hash = hashFields(hash, getAllFields()); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + } return hash; } + + private static ByteString toByteString(Object value) { + if (value instanceof byte[]) { + return ByteString.copyFrom((byte[]) value); + } else { + return (ByteString) value; + } + } + + /** + * Compares two bytes fields. The parameters must be either a byte array or a + * ByteString object. They can be of different type though. + */ + private static boolean compareBytes(Object a, Object b) { + if (a instanceof byte[] && b instanceof byte[]) { + return Arrays.equals((byte[])a, (byte[])b); + } + return toByteString(a).equals(toByteString(b)); + } + + /** + * Compares two set of fields. + * This method is used to implement {@link AbstractMessage#equals(Object)} + * and {@link AbstractMutableMessage#equals(Object)}. It takes special care + * of bytes fields because immutable messages and mutable messages use + * different Java type to reprensent a bytes field and this method should be + * able to compare immutable messages, mutable messages and also an immutable + * message to a mutable message. + */ + static boolean compareFields(Map a, + Map b) { + if (a.size() != b.size()) { + return false; + } + for (FieldDescriptor descriptor : a.keySet()) { + if (!b.containsKey(descriptor)) { + return false; + } + Object value1 = a.get(descriptor); + Object value2 = b.get(descriptor); + if (descriptor.getType() == FieldDescriptor.Type.BYTES) { + if (descriptor.isRepeated()) { + List list1 = (List) value1; + List list2 = (List) value2; + if (list1.size() != list2.size()) { + return false; + } + for (int i = 0; i < list1.size(); i++) { + if (!compareBytes(list1.get(i), list2.get(i))) { + return false; + } + } + } else { + // Compares a singular bytes field. + if (!compareBytes(value1, value2)) { + return false; + } + } + } else { + // Compare non-bytes fields. + if (!value1.equals(value2)) { + return false; + } + } + } + return true; + } + + /** Get a hash code for given fields and values, using the given seed. */ + @SuppressWarnings("unchecked") + protected static int hashFields(int hash, Map map) { + for (Map.Entry entry : map.entrySet()) { + FieldDescriptor field = entry.getKey(); + Object value = entry.getValue(); + hash = (37 * hash) + field.getNumber(); + if (field.getType() != FieldDescriptor.Type.ENUM){ + hash = (53 * hash) + value.hashCode(); + } else if (field.isRepeated()) { + List list = (List) value; + hash = (53 * hash) + Internal.hashEnumList(list); + } else { + hash = (53 * hash) + Internal.hashEnum((EnumLite) value); + } + } + return hash; + } + + /** + * Package private helper method for AbstractParser to create + * UninitializedMessageException with missing field information. + */ + @Override + UninitializedMessageException newUninitializedMessageException() { + return Builder.newUninitializedMessageException(this); + } // ================================================================= @@ -187,6 +234,25 @@ public abstract class AbstractMessage extends AbstractMessageLite @Override public abstract BuilderType clone(); + /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ + @Override + public boolean hasOneof(OneofDescriptor oneof) { + throw new UnsupportedOperationException("hasOneof() is not implemented."); + } + + /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ + @Override + public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) { + throw new UnsupportedOperationException( + "getOneofFieldDescriptor() is not implemented."); + } + + /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ + @Override + public BuilderType clearOneof(OneofDescriptor oneof) { + throw new UnsupportedOperationException("clearOneof() is not implemented."); + } + public BuilderType clear() { for (final Map.Entry entry : getAllFields().entrySet()) { @@ -195,6 +261,14 @@ public abstract class AbstractMessage extends AbstractMessageLite return (BuilderType) this; } + public List findInitializationErrors() { + return MessageReflection.findMissingFields(this); + } + + public String getInitializationErrorString() { + return MessageReflection.delimitWithCommas(findInitializationErrors()); + } + public BuilderType mergeFrom(final Message other) { if (other.getDescriptorForType() != getDescriptorForType()) { throw new IllegalArgumentException( @@ -257,8 +331,13 @@ public abstract class AbstractMessage extends AbstractMessageLite break; } - if (!mergeFieldFrom(input, unknownFields, extensionRegistry, - this, tag)) { + MessageReflection.BuilderAdapter builderAdapter = + new MessageReflection.BuilderAdapter(this); + if (!MessageReflection.mergeFieldFrom(input, unknownFields, + extensionRegistry, + getDescriptorForType(), + builderAdapter, + tag)) { // end group tag break; } @@ -267,272 +346,6 @@ public abstract class AbstractMessage extends AbstractMessageLite return (BuilderType) this; } - /** - * Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder, - * ExtensionRegistryLite, Message.Builder)}, but parses a single field. - * Package-private because it is used by GeneratedMessage.ExtendableMessage. - * @param tag The tag, which should have already been read. - * @return {@code true} unless the tag is an end-group tag. - */ - @SuppressWarnings("unchecked") - static boolean mergeFieldFrom( - final CodedInputStream input, - final UnknownFieldSet.Builder unknownFields, - final ExtensionRegistryLite extensionRegistry, - final Message.Builder builder, - final int tag) throws IOException { - final Descriptor type = builder.getDescriptorForType(); - - if (type.getOptions().getMessageSetWireFormat() && - tag == WireFormat.MESSAGE_SET_ITEM_TAG) { - mergeMessageSetExtensionFromCodedStream( - input, unknownFields, extensionRegistry, builder); - return true; - } - - final int wireType = WireFormat.getTagWireType(tag); - final int fieldNumber = WireFormat.getTagFieldNumber(tag); - - final FieldDescriptor field; - Message defaultInstance = null; - - if (type.isExtensionNumber(fieldNumber)) { - // extensionRegistry may be either ExtensionRegistry or - // ExtensionRegistryLite. Since the type we are parsing is a full - // message, only a full ExtensionRegistry could possibly contain - // extensions of it. Otherwise we will treat the registry as if it - // were empty. - if (extensionRegistry instanceof ExtensionRegistry) { - final ExtensionRegistry.ExtensionInfo extension = - ((ExtensionRegistry) extensionRegistry) - .findExtensionByNumber(type, fieldNumber); - if (extension == null) { - field = null; - } else { - field = extension.descriptor; - defaultInstance = extension.defaultInstance; - if (defaultInstance == null && - field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - throw new IllegalStateException( - "Message-typed extension lacked default instance: " + - field.getFullName()); - } - } - } else { - field = null; - } - } else { - field = type.findFieldByNumber(fieldNumber); - } - - boolean unknown = false; - boolean packed = false; - if (field == null) { - unknown = true; // Unknown field. - } else if (wireType == FieldSet.getWireFormatForFieldType( - field.getLiteType(), - false /* isPacked */)) { - packed = false; - } else if (field.isPackable() && - wireType == FieldSet.getWireFormatForFieldType( - field.getLiteType(), - true /* isPacked */)) { - packed = true; - } else { - unknown = true; // Unknown wire type. - } - - if (unknown) { // Unknown field or wrong wire type. Skip. - return unknownFields.mergeFieldFrom(tag, input); - } - - if (packed) { - final int length = input.readRawVarint32(); - final int limit = input.pushLimit(length); - if (field.getLiteType() == WireFormat.FieldType.ENUM) { - while (input.getBytesUntilLimit() > 0) { - final int rawValue = input.readEnum(); - final Object value = field.getEnumType().findValueByNumber(rawValue); - if (value == null) { - // If the number isn't recognized as a valid value for this - // enum, drop it (don't even add it to unknownFields). - return true; - } - builder.addRepeatedField(field, value); - } - } else { - while (input.getBytesUntilLimit() > 0) { - final Object value = - FieldSet.readPrimitiveField(input, field.getLiteType()); - builder.addRepeatedField(field, value); - } - } - input.popLimit(limit); - } else { - final Object value; - switch (field.getType()) { - case GROUP: { - final Message.Builder subBuilder; - if (defaultInstance != null) { - subBuilder = defaultInstance.newBuilderForType(); - } else { - subBuilder = builder.newBuilderForField(field); - } - if (!field.isRepeated()) { - subBuilder.mergeFrom((Message) builder.getField(field)); - } - input.readGroup(field.getNumber(), subBuilder, extensionRegistry); - value = subBuilder.build(); - break; - } - case MESSAGE: { - final Message.Builder subBuilder; - if (defaultInstance != null) { - subBuilder = defaultInstance.newBuilderForType(); - } else { - subBuilder = builder.newBuilderForField(field); - } - if (!field.isRepeated()) { - subBuilder.mergeFrom((Message) builder.getField(field)); - } - input.readMessage(subBuilder, extensionRegistry); - value = subBuilder.build(); - break; - } - case ENUM: - final int rawValue = input.readEnum(); - value = field.getEnumType().findValueByNumber(rawValue); - // If the number isn't recognized as a valid value for this enum, - // drop it. - if (value == null) { - unknownFields.mergeVarintField(fieldNumber, rawValue); - return true; - } - break; - default: - value = FieldSet.readPrimitiveField(input, field.getLiteType()); - break; - } - - if (field.isRepeated()) { - builder.addRepeatedField(field, value); - } else { - builder.setField(field, value); - } - } - - return true; - } - - /** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */ - private static void mergeMessageSetExtensionFromCodedStream( - final CodedInputStream input, - final UnknownFieldSet.Builder unknownFields, - final ExtensionRegistryLite extensionRegistry, - final Message.Builder builder) throws IOException { - final Descriptor type = builder.getDescriptorForType(); - - // The wire format for MessageSet is: - // message MessageSet { - // repeated group Item = 1 { - // required int32 typeId = 2; - // required bytes message = 3; - // } - // } - // "typeId" is the extension's field number. The extension can only be - // a message type, where "message" contains the encoded bytes of that - // message. - // - // In practice, we will probably never see a MessageSet item in which - // the message appears before the type ID, or where either field does not - // appear exactly once. However, in theory such cases are valid, so we - // should be prepared to accept them. - - int typeId = 0; - ByteString rawBytes = null; // If we encounter "message" before "typeId" - Message.Builder subBuilder = null; - FieldDescriptor field = null; - - while (true) { - final int tag = input.readTag(); - if (tag == 0) { - break; - } - - if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) { - typeId = input.readUInt32(); - // Zero is not a valid type ID. - if (typeId != 0) { - final ExtensionRegistry.ExtensionInfo extension; - - // extensionRegistry may be either ExtensionRegistry or - // ExtensionRegistryLite. Since the type we are parsing is a full - // message, only a full ExtensionRegistry could possibly contain - // extensions of it. Otherwise we will treat the registry as if it - // were empty. - if (extensionRegistry instanceof ExtensionRegistry) { - extension = ((ExtensionRegistry) extensionRegistry) - .findExtensionByNumber(type, typeId); - } else { - extension = null; - } - - if (extension != null) { - field = extension.descriptor; - subBuilder = extension.defaultInstance.newBuilderForType(); - final Message originalMessage = (Message)builder.getField(field); - if (originalMessage != null) { - subBuilder.mergeFrom(originalMessage); - } - if (rawBytes != null) { - // We already encountered the message. Parse it now. - subBuilder.mergeFrom( - CodedInputStream.newInstance(rawBytes.newInput())); - rawBytes = null; - } - } else { - // Unknown extension number. If we already saw data, put it - // in rawBytes. - if (rawBytes != null) { - unknownFields.mergeField(typeId, - UnknownFieldSet.Field.newBuilder() - .addLengthDelimited(rawBytes) - .build()); - rawBytes = null; - } - } - } - } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) { - if (typeId == 0) { - // We haven't seen a type ID yet, so we have to store the raw bytes - // for now. - rawBytes = input.readBytes(); - } else if (subBuilder == null) { - // We don't know how to parse this. Ignore it. - unknownFields.mergeField(typeId, - UnknownFieldSet.Field.newBuilder() - .addLengthDelimited(input.readBytes()) - .build()); - } else { - // We already know the type, so we can parse directly from the input - // with no copying. Hooray! - input.readMessage(subBuilder, extensionRegistry); - } - } else { - // Unknown tag. Skip it. - if (!input.skipField(tag)) { - break; // end of group - } - } - } - - input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG); - - if (subBuilder != null) { - builder.setField(field, subBuilder.build()); - } - } - public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) { setUnknownFields( UnknownFieldSet.newBuilder(getUnknownFields()) @@ -541,78 +354,23 @@ public abstract class AbstractMessage extends AbstractMessageLite return (BuilderType) this; } + public Message.Builder getFieldBuilder(final FieldDescriptor field) { + throw new UnsupportedOperationException( + "getFieldBuilder() called on an unsupported message type."); + } + + public String toString() { + return TextFormat.printToString(this); + } + /** * Construct an UninitializedMessageException reporting missing fields in * the given message. */ protected static UninitializedMessageException newUninitializedMessageException(Message message) { - return new UninitializedMessageException(findMissingFields(message)); - } - - /** - * Populates {@code this.missingFields} with the full "path" of each - * missing required field in the given message. - */ - private static List findMissingFields(final Message message) { - final List results = new ArrayList(); - findMissingFields(message, "", results); - return results; - } - - /** Recursive helper implementing {@link #findMissingFields(Message)}. */ - private static void findMissingFields(final Message message, - final String prefix, - final List results) { - for (final FieldDescriptor field : - message.getDescriptorForType().getFields()) { - if (field.isRequired() && !message.hasField(field)) { - results.add(prefix + field.getName()); - } - } - - for (final Map.Entry entry : - message.getAllFields().entrySet()) { - final FieldDescriptor field = entry.getKey(); - final Object value = entry.getValue(); - - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - if (field.isRepeated()) { - int i = 0; - for (final Object element : (List) value) { - findMissingFields((Message) element, - subMessagePrefix(prefix, field, i++), - results); - } - } else { - if (message.hasField(field)) { - findMissingFields((Message) value, - subMessagePrefix(prefix, field, -1), - results); - } - } - } - } - } - - private static String subMessagePrefix(final String prefix, - final FieldDescriptor field, - final int index) { - final StringBuilder result = new StringBuilder(prefix); - if (field.isExtension()) { - result.append('(') - .append(field.getFullName()) - .append(')'); - } else { - result.append(field.getName()); - } - if (index != -1) { - result.append('[') - .append(index) - .append(']'); - } - result.append('.'); - return result.toString(); + return new UninitializedMessageException( + MessageReflection.findMissingFields(message)); } // =============================================================== @@ -704,6 +462,5 @@ public abstract class AbstractMessage extends AbstractMessageLite throws IOException { return super.mergeDelimitedFrom(input, extensionRegistry); } - } } diff --git a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java index 9210d85..bce713b 100644 --- a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java +++ b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java @@ -44,6 +44,8 @@ import java.util.Collection; * @author kenton@google.com Kenton Varda */ public abstract class AbstractMessageLite implements MessageLite { + protected int memoizedHashCode = 0; + public ByteString toByteString() { try { final ByteString.CodedBuilder out = @@ -91,6 +93,22 @@ public abstract class AbstractMessageLite implements MessageLite { codedOutput.flush(); } + + /** + * Package private helper method for AbstractParser to create + * UninitializedMessageException. + */ + UninitializedMessageException newUninitializedMessageException() { + return new UninitializedMessageException(this); + } + + protected static void checkByteStringIsUtf8(ByteString byteString) + throws IllegalArgumentException { + if (!byteString.isValidUtf8()) { + throw new IllegalArgumentException("Byte string is not UTF-8."); + } + } + /** * A partial implementation of the {@link Message.Builder} interface which * implements as many methods of that interface as possible in terms of @@ -303,24 +321,35 @@ public abstract class AbstractMessageLite implements MessageLite { * used by generated code. Users should ignore it. * * @throws NullPointerException if any of the elements of {@code values} is - * null. + * null. When that happens, some elements of {@code values} may have already + * been added to the result {@code list}. */ protected static void addAll(final Iterable values, final Collection list) { - for (final T value : values) { - if (value == null) { - throw new NullPointerException(); - } - } - if (values instanceof Collection) { - @SuppressWarnings("unsafe") final - Collection collection = (Collection) values; - list.addAll(collection); + if (values instanceof LazyStringList) { + // For StringOrByteStringLists, check the underlying elements to avoid + // forcing conversions of ByteStrings to Strings. + checkForNullValues(((LazyStringList) values).getUnderlyingElements()); + list.addAll((Collection) values); + } else if (values instanceof Collection) { + checkForNullValues(values); + list.addAll((Collection) values); } else { for (final T value : values) { + if (value == null) { + throw new NullPointerException(); + } list.add(value); } } } + + private static void checkForNullValues(final Iterable values) { + for (final Object value : values) { + if (value == null) { + throw new NullPointerException(); + } + } + } } } diff --git a/java/src/main/java/com/google/protobuf/AbstractParser.java b/java/src/main/java/com/google/protobuf/AbstractParser.java new file mode 100644 index 0000000..3f30124 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/AbstractParser.java @@ -0,0 +1,253 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream; + +import java.io.IOException; +import java.io.InputStream; + +/** + * A partial implementation of the {@link Parser} interface which implements + * as many methods of that interface as possible in terms of other methods. + * + * Note: This class implements all the convenience methods in the + * {@link Parser} interface. See {@link Parser} for related javadocs. + * Subclasses need to implement + * {@link Parser#parsePartialFrom(CodedInputStream, ExtensionRegistryLite)} + * + * @author liujisi@google.com (Pherl Liu) + */ +public abstract class AbstractParser + implements Parser { + /** + * Creates an UninitializedMessageException for MessageType. + */ + private UninitializedMessageException + newUninitializedMessageException(MessageType message) { + if (message instanceof AbstractMessageLite) { + return ((AbstractMessageLite) message).newUninitializedMessageException(); + } + return new UninitializedMessageException(message); + } + + /** + * Helper method to check if message is initialized. + * + * @throws InvalidProtocolBufferException if it is not initialized. + * @return The message to check. + */ + private MessageType checkMessageInitialized(MessageType message) + throws InvalidProtocolBufferException { + if (message != null && !message.isInitialized()) { + throw newUninitializedMessageException(message) + .asInvalidProtocolBufferException() + .setUnfinishedMessage(message); + } + return message; + } + + private static final ExtensionRegistryLite EMPTY_REGISTRY + = ExtensionRegistryLite.getEmptyRegistry(); + + public MessageType parsePartialFrom(CodedInputStream input) + throws InvalidProtocolBufferException { + return parsePartialFrom(input, EMPTY_REGISTRY); + } + + public MessageType parseFrom(CodedInputStream input, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return checkMessageInitialized( + parsePartialFrom(input, extensionRegistry)); + } + + public MessageType parseFrom(CodedInputStream input) + throws InvalidProtocolBufferException { + return parseFrom(input, EMPTY_REGISTRY); + } + + public MessageType parsePartialFrom(ByteString data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + MessageType message; + try { + CodedInputStream input = data.newCodedInput(); + message = parsePartialFrom(input, extensionRegistry); + try { + input.checkLastTagWas(0); + } catch (InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(message); + } + return message; + } catch (InvalidProtocolBufferException e) { + throw e; + } + } + + public MessageType parsePartialFrom(ByteString data) + throws InvalidProtocolBufferException { + return parsePartialFrom(data, EMPTY_REGISTRY); + } + + public MessageType parseFrom(ByteString data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return checkMessageInitialized(parsePartialFrom(data, extensionRegistry)); + } + + public MessageType parseFrom(ByteString data) + throws InvalidProtocolBufferException { + return parseFrom(data, EMPTY_REGISTRY); + } + + public MessageType parsePartialFrom(byte[] data, int off, int len, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + try { + CodedInputStream input = CodedInputStream.newInstance(data, off, len); + MessageType message = parsePartialFrom(input, extensionRegistry); + try { + input.checkLastTagWas(0); + } catch (InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(message); + } + return message; + } catch (InvalidProtocolBufferException e) { + throw e; + } + } + + public MessageType parsePartialFrom(byte[] data, int off, int len) + throws InvalidProtocolBufferException { + return parsePartialFrom(data, off, len, EMPTY_REGISTRY); + } + + public MessageType parsePartialFrom(byte[] data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return parsePartialFrom(data, 0, data.length, extensionRegistry); + } + + public MessageType parsePartialFrom(byte[] data) + throws InvalidProtocolBufferException { + return parsePartialFrom(data, 0, data.length, EMPTY_REGISTRY); + } + + public MessageType parseFrom(byte[] data, int off, int len, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return checkMessageInitialized( + parsePartialFrom(data, off, len, extensionRegistry)); + } + + public MessageType parseFrom(byte[] data, int off, int len) + throws InvalidProtocolBufferException { + return parseFrom(data, off, len, EMPTY_REGISTRY); + } + + public MessageType parseFrom(byte[] data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return parseFrom(data, 0, data.length, extensionRegistry); + } + + public MessageType parseFrom(byte[] data) + throws InvalidProtocolBufferException { + return parseFrom(data, EMPTY_REGISTRY); + } + + public MessageType parsePartialFrom(InputStream input, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + CodedInputStream codedInput = CodedInputStream.newInstance(input); + MessageType message = parsePartialFrom(codedInput, extensionRegistry); + try { + codedInput.checkLastTagWas(0); + } catch (InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(message); + } + return message; + } + + public MessageType parsePartialFrom(InputStream input) + throws InvalidProtocolBufferException { + return parsePartialFrom(input, EMPTY_REGISTRY); + } + + public MessageType parseFrom(InputStream input, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return checkMessageInitialized( + parsePartialFrom(input, extensionRegistry)); + } + + public MessageType parseFrom(InputStream input) + throws InvalidProtocolBufferException { + return parseFrom(input, EMPTY_REGISTRY); + } + + public MessageType parsePartialDelimitedFrom( + InputStream input, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + int size; + try { + int firstByte = input.read(); + if (firstByte == -1) { + return null; + } + size = CodedInputStream.readRawVarint32(firstByte, input); + } catch (IOException e) { + throw new InvalidProtocolBufferException(e.getMessage()); + } + InputStream limitedInput = new LimitedInputStream(input, size); + return parsePartialFrom(limitedInput, extensionRegistry); + } + + public MessageType parsePartialDelimitedFrom(InputStream input) + throws InvalidProtocolBufferException { + return parsePartialDelimitedFrom(input, EMPTY_REGISTRY); + } + + public MessageType parseDelimitedFrom( + InputStream input, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return checkMessageInitialized( + parsePartialDelimitedFrom(input, extensionRegistry)); + } + + public MessageType parseDelimitedFrom(InputStream input) + throws InvalidProtocolBufferException { + return parseDelimitedFrom(input, EMPTY_REGISTRY); + } +} diff --git a/java/src/main/java/com/google/protobuf/BoundedByteString.java b/java/src/main/java/com/google/protobuf/BoundedByteString.java new file mode 100644 index 0000000..cd4982c --- /dev/null +++ b/java/src/main/java/com/google/protobuf/BoundedByteString.java @@ -0,0 +1,163 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.util.NoSuchElementException; + +/** + * This class is used to represent the substring of a {@link ByteString} over a + * single byte array. In terms of the public API of {@link ByteString}, you end + * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link + * ByteString#substring(int, int)}. + * + *

This class contains most of the overhead involved in creating a substring + * from a {@link LiteralByteString}. The overhead involves some range-checking + * and two extra fields. + * + * @author carlanton@google.com (Carl Haverl) + */ +class BoundedByteString extends LiteralByteString { + + private final int bytesOffset; + private final int bytesLength; + + /** + * Creates a {@code BoundedByteString} backed by the sub-range of given array, + * without copying. + * + * @param bytes array to wrap + * @param offset index to first byte to use in bytes + * @param length number of bytes to use from bytes + * @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0}, + * or if {@code offset + length > + * bytes.length}. + */ + BoundedByteString(byte[] bytes, int offset, int length) { + super(bytes); + if (offset < 0) { + throw new IllegalArgumentException("Offset too small: " + offset); + } + if (length < 0) { + throw new IllegalArgumentException("Length too small: " + offset); + } + if ((long) offset + length > bytes.length) { + throw new IllegalArgumentException( + "Offset+Length too large: " + offset + "+" + length); + } + + this.bytesOffset = offset; + this.bytesLength = length; + } + + /** + * Gets the byte at the given index. + * Throws {@link ArrayIndexOutOfBoundsException} + * for backwards-compatibility reasons although it would more properly be + * {@link IndexOutOfBoundsException}. + * + * @param index index of byte + * @return the value + * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size + */ + @Override + public byte byteAt(int index) { + // We must check the index ourselves as we cannot rely on Java array index + // checking for substrings. + if (index < 0) { + throw new ArrayIndexOutOfBoundsException("Index too small: " + index); + } + if (index >= size()) { + throw new ArrayIndexOutOfBoundsException( + "Index too large: " + index + ", " + size()); + } + + return bytes[bytesOffset + index]; + } + + @Override + public int size() { + return bytesLength; + } + + @Override + protected int getOffsetIntoBytes() { + return bytesOffset; + } + + // ================================================================= + // ByteString -> byte[] + + @Override + protected void copyToInternal(byte[] target, int sourceOffset, + int targetOffset, int numberToCopy) { + System.arraycopy(bytes, getOffsetIntoBytes() + sourceOffset, target, + targetOffset, numberToCopy); + } + + // ================================================================= + // ByteIterator + + @Override + public ByteIterator iterator() { + return new BoundedByteIterator(); + } + + private class BoundedByteIterator implements ByteIterator { + + private int position; + private final int limit; + + private BoundedByteIterator() { + position = getOffsetIntoBytes(); + limit = position + size(); + } + + public boolean hasNext() { + return (position < limit); + } + + public Byte next() { + // Boxing calls Byte.valueOf(byte), which does not instantiate. + return nextByte(); + } + + public byte nextByte() { + if (position >= limit) { + throw new NoSuchElementException(); + } + return bytes[position++]; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java index 5fade03..89b5789 100644 --- a/java/src/main/java/com/google/protobuf/ByteString.java +++ b/java/src/main/java/com/google/protobuf/ByteString.java @@ -30,140 +30,426 @@ package com.google.protobuf; -import java.io.InputStream; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; import java.util.List; +import java.util.NoSuchElementException; /** - * Immutable array of bytes. + * Immutable sequence of bytes. Substring is supported by sharing the reference + * to the immutable underlying bytes, as with {@link String}. Concatenation is + * likewise supported without copying (long strings) by building a tree of + * pieces in {@link RopeByteString}. + *

+ * Like {@link String}, the contents of a {@link ByteString} can never be + * observed to change, not even in the presence of a data race or incorrect + * API usage in the client code. * * @author crazybob@google.com Bob Lee * @author kenton@google.com Kenton Varda + * @author carlanton@google.com Carl Haverl + * @author martinrb@google.com Martin Buchholz */ -public final class ByteString { - private final byte[] bytes; +public abstract class ByteString implements Iterable { - private ByteString(final byte[] bytes) { - this.bytes = bytes; - } + /** + * When two strings to be concatenated have a combined length shorter than + * this, we just copy their bytes on {@link #concat(ByteString)}. + * The trade-off is copy size versus the overhead of creating tree nodes + * in {@link RopeByteString}. + */ + static final int CONCATENATE_BY_COPY_SIZE = 128; + + /** + * When copying an InputStream into a ByteString with .readFrom(), + * the chunks in the underlying rope start at 256 bytes, but double + * each iteration up to 8192 bytes. + */ + static final int MIN_READ_FROM_CHUNK_SIZE = 0x100; // 256b + static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k /** - * Gets the byte at the given index. + * Empty {@code ByteString}. + */ + public static final ByteString EMPTY = new LiteralByteString(new byte[0]); + + // This constructor is here to prevent subclassing outside of this package, + ByteString() {} + + /** + * Gets the byte at the given index. This method should be used only for + * random access to individual bytes. To access bytes sequentially, use the + * {@link ByteIterator} returned by {@link #iterator()}, and call {@link + * #substring(int, int)} first if necessary. * + * @param index index of byte + * @return the value * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size */ - public byte byteAt(final int index) { - return bytes[index]; + public abstract byte byteAt(int index); + + /** + * Return a {@link ByteString.ByteIterator} over the bytes in the ByteString. + * To avoid auto-boxing, you may get the iterator manually and call + * {@link ByteIterator#nextByte()}. + * + * @return the iterator + */ + public abstract ByteIterator iterator(); + + /** + * This interface extends {@code Iterator}, so that we can return an + * unboxed {@code byte}. + */ + public interface ByteIterator extends Iterator { + /** + * An alternative to {@link Iterator#next()} that returns an + * unboxed primitive {@code byte}. + * + * @return the next {@code byte} in the iteration + * @throws NoSuchElementException if the iteration has no more elements + */ + byte nextByte(); } /** * Gets the number of bytes. + * + * @return size in bytes */ - public int size() { - return bytes.length; - } + public abstract int size(); /** * Returns {@code true} if the size is {@code 0}, {@code false} otherwise. + * + * @return true if this is zero bytes long */ public boolean isEmpty() { - return bytes.length == 0; + return size() == 0; } // ================================================================= - // byte[] -> ByteString + // ByteString -> substring + + /** + * Return the substring from {@code beginIndex}, inclusive, to the end of the + * string. + * + * @param beginIndex start at this index + * @return substring sharing underlying data + * @throws IndexOutOfBoundsException if {@code beginIndex < 0} or + * {@code beginIndex > size()}. + */ + public ByteString substring(int beginIndex) { + return substring(beginIndex, size()); + } + + /** + * Return the substring from {@code beginIndex}, inclusive, to {@code + * endIndex}, exclusive. + * + * @param beginIndex start at this index + * @param endIndex the last character is the one before this index + * @return substring sharing underlying data + * @throws IndexOutOfBoundsException if {@code beginIndex < 0}, + * {@code endIndex > size()}, or {@code beginIndex > endIndex}. + */ + public abstract ByteString substring(int beginIndex, int endIndex); /** - * Empty ByteString. + * Tests if this bytestring starts with the specified prefix. + * Similar to {@link String#startsWith(String)} + * + * @param prefix the prefix. + * @return true if the byte sequence represented by the + * argument is a prefix of the byte sequence represented by + * this string; false otherwise. */ - public static final ByteString EMPTY = new ByteString(new byte[0]); + public boolean startsWith(ByteString prefix) { + return size() >= prefix.size() && + substring(0, prefix.size()).equals(prefix); + } + + /** + * Tests if this bytestring ends with the specified suffix. + * Similar to {@link String#endsWith(String)} + * + * @param suffix the suffix. + * @return true if the byte sequence represented by the + * argument is a suffix of the byte sequence represented by + * this string; false otherwise. + */ + public boolean endsWith(ByteString suffix) { + return size() >= suffix.size() && + substring(size() - suffix.size()).equals(suffix); + } + + // ================================================================= + // byte[] -> ByteString /** * Copies the given bytes into a {@code ByteString}. + * + * @param bytes source array + * @param offset offset in source array + * @param size number of bytes to copy + * @return new {@code ByteString} */ - public static ByteString copyFrom(final byte[] bytes, final int offset, - final int size) { - final byte[] copy = new byte[size]; + public static ByteString copyFrom(byte[] bytes, int offset, int size) { + byte[] copy = new byte[size]; System.arraycopy(bytes, offset, copy, 0, size); - return new ByteString(copy); + return new LiteralByteString(copy); } /** * Copies the given bytes into a {@code ByteString}. + * + * @param bytes to copy + * @return new {@code ByteString} */ - public static ByteString copyFrom(final byte[] bytes) { + public static ByteString copyFrom(byte[] bytes) { return copyFrom(bytes, 0, bytes.length); } /** - * Copies {@code size} bytes from a {@code java.nio.ByteBuffer} into + * Copies the next {@code size} bytes from a {@code java.nio.ByteBuffer} into * a {@code ByteString}. + * + * @param bytes source buffer + * @param size number of bytes to copy + * @return new {@code ByteString} */ - public static ByteString copyFrom(final ByteBuffer bytes, final int size) { - final byte[] copy = new byte[size]; + public static ByteString copyFrom(ByteBuffer bytes, int size) { + byte[] copy = new byte[size]; bytes.get(copy); - return new ByteString(copy); + return new LiteralByteString(copy); } /** * Copies the remaining bytes from a {@code java.nio.ByteBuffer} into * a {@code ByteString}. + * + * @param bytes sourceBuffer + * @return new {@code ByteString} */ - public static ByteString copyFrom(final ByteBuffer bytes) { + public static ByteString copyFrom(ByteBuffer bytes) { return copyFrom(bytes, bytes.remaining()); } /** * Encodes {@code text} into a sequence of bytes using the named charset * and returns the result as a {@code ByteString}. + * + * @param text source string + * @param charsetName encoding to use + * @return new {@code ByteString} + * @throws UnsupportedEncodingException if the encoding isn't found */ - public static ByteString copyFrom(final String text, final String charsetName) + public static ByteString copyFrom(String text, String charsetName) throws UnsupportedEncodingException { - return new ByteString(text.getBytes(charsetName)); + return new LiteralByteString(text.getBytes(charsetName)); } /** * Encodes {@code text} into a sequence of UTF-8 bytes and returns the * result as a {@code ByteString}. + * + * @param text source string + * @return new {@code ByteString} */ - public static ByteString copyFromUtf8(final String text) { + public static ByteString copyFromUtf8(String text) { try { - return new ByteString(text.getBytes("UTF-8")); + return new LiteralByteString(text.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { throw new RuntimeException("UTF-8 not supported?", e); } } + // ================================================================= + // InputStream -> ByteString + + /** + * Completely reads the given stream's bytes into a + * {@code ByteString}, blocking if necessary until all bytes are + * read through to the end of the stream. + * + * Performance notes: The returned {@code ByteString} is an + * immutable tree of byte arrays ("chunks") of the stream data. The + * first chunk is small, with subsequent chunks each being double + * the size, up to 8K. If the caller knows the precise length of + * the stream and wishes to avoid all unnecessary copies and + * allocations, consider using the two-argument version of this + * method, below. + * + * @param streamToDrain The source stream, which is read completely + * but not closed. + * @return A new {@code ByteString} which is made up of chunks of + * various sizes, depending on the behavior of the underlying + * stream. + * @throws IOException IOException is thrown if there is a problem + * reading the underlying stream. + */ + public static ByteString readFrom(InputStream streamToDrain) + throws IOException { + return readFrom( + streamToDrain, MIN_READ_FROM_CHUNK_SIZE, MAX_READ_FROM_CHUNK_SIZE); + } + + /** + * Completely reads the given stream's bytes into a + * {@code ByteString}, blocking if necessary until all bytes are + * read through to the end of the stream. + * + * Performance notes: The returned {@code ByteString} is an + * immutable tree of byte arrays ("chunks") of the stream data. The + * chunkSize parameter sets the size of these byte arrays. In + * particular, if the chunkSize is precisely the same as the length + * of the stream, unnecessary allocations and copies will be + * avoided. Otherwise, the chunks will be of the given size, except + * for the last chunk, which will be resized (via a reallocation and + * copy) to contain the remainder of the stream. + * + * @param streamToDrain The source stream, which is read completely + * but not closed. + * @param chunkSize The size of the chunks in which to read the + * stream. + * @return A new {@code ByteString} which is made up of chunks of + * the given size. + * @throws IOException IOException is thrown if there is a problem + * reading the underlying stream. + */ + public static ByteString readFrom(InputStream streamToDrain, int chunkSize) + throws IOException { + return readFrom(streamToDrain, chunkSize, chunkSize); + } + + // Helper method that takes the chunk size range as a parameter. + public static ByteString readFrom(InputStream streamToDrain, int minChunkSize, + int maxChunkSize) throws IOException { + Collection results = new ArrayList(); + + // copy the inbound bytes into a list of chunks; the chunk size + // grows exponentially to support both short and long streams. + int chunkSize = minChunkSize; + while (true) { + ByteString chunk = readChunk(streamToDrain, chunkSize); + if (chunk == null) { + break; + } + results.add(chunk); + chunkSize = Math.min(chunkSize * 2, maxChunkSize); + } + + return ByteString.copyFrom(results); + } + + /** + * Blocks until a chunk of the given size can be made from the + * stream, or EOF is reached. Calls read() repeatedly in case the + * given stream implementation doesn't completely fill the given + * buffer in one read() call. + * + * @return A chunk of the desired size, or else a chunk as large as + * was available when end of stream was reached. Returns null if the + * given stream had no more data in it. + */ + private static ByteString readChunk(InputStream in, final int chunkSize) + throws IOException { + final byte[] buf = new byte[chunkSize]; + int bytesRead = 0; + while (bytesRead < chunkSize) { + final int count = in.read(buf, bytesRead, chunkSize - bytesRead); + if (count == -1) { + break; + } + bytesRead += count; + } + + if (bytesRead == 0) { + return null; + } else { + return ByteString.copyFrom(buf, 0, bytesRead); + } + } + + // ================================================================= + // Multiple ByteStrings -> One ByteString + + /** + * Concatenate the given {@code ByteString} to this one. Short concatenations, + * of total size smaller than {@link ByteString#CONCATENATE_BY_COPY_SIZE}, are + * produced by copying the underlying bytes (as per Rope.java, + * BAP95 . In general, the concatenate involves no copying. + * + * @param other string to concatenate + * @return a new {@code ByteString} instance + */ + public ByteString concat(ByteString other) { + int thisSize = size(); + int otherSize = other.size(); + if ((long) thisSize + otherSize >= Integer.MAX_VALUE) { + throw new IllegalArgumentException("ByteString would be too long: " + + thisSize + "+" + otherSize); + } + + return RopeByteString.concatenate(this, other); + } + /** - * Concatenates all byte strings in the list and returns the result. + * Concatenates all byte strings in the iterable and returns the result. + * This is designed to run in O(list size), not O(total bytes). * *

The returned {@code ByteString} is not necessarily a unique object. * If the list is empty, the returned object is the singleton empty * {@code ByteString}. If the list has only one element, that * {@code ByteString} will be returned without copying. + * + * @param byteStrings strings to be concatenated + * @return new {@code ByteString} */ - public static ByteString copyFrom(List list) { - if (list.size() == 0) { - return EMPTY; - } else if (list.size() == 1) { - return list.get(0); + public static ByteString copyFrom(Iterable byteStrings) { + Collection collection; + if (!(byteStrings instanceof Collection)) { + collection = new ArrayList(); + for (ByteString byteString : byteStrings) { + collection.add(byteString); + } + } else { + collection = (Collection) byteStrings; } - - int size = 0; - for (ByteString str : list) { - size += str.size(); + ByteString result; + if (collection.isEmpty()) { + result = EMPTY; + } else { + result = balancedConcat(collection.iterator(), collection.size()); } - byte[] bytes = new byte[size]; - int pos = 0; - for (ByteString str : list) { - System.arraycopy(str.bytes, 0, bytes, pos, str.size()); - pos += str.size(); + return result; + } + + // Internal function used by copyFrom(Iterable). + // Create a balanced concatenation of the next "length" elements from the + // iterable. + private static ByteString balancedConcat(Iterator iterator, + int length) { + assert length >= 1; + ByteString result; + if (length == 1) { + result = iterator.next(); + } else { + int halfLength = length >>> 1; + ByteString left = balancedConcat(iterator, halfLength); + ByteString right = balancedConcat(iterator, length - halfLength); + result = left.concat(right); } - return new ByteString(bytes); + return result; } // ================================================================= @@ -174,194 +460,493 @@ public final class ByteString { * * @param target buffer to copy into * @param offset in the target buffer + * @throws IndexOutOfBoundsException if the offset is negative or too large */ - public void copyTo(final byte[] target, final int offset) { - System.arraycopy(bytes, 0, target, offset, bytes.length); + public void copyTo(byte[] target, int offset) { + copyTo(target, 0, offset, size()); } /** * Copies bytes into a buffer. * - * @param target buffer to copy into + * @param target buffer to copy into * @param sourceOffset offset within these bytes * @param targetOffset offset within the target buffer - * @param size number of bytes to copy + * @param numberToCopy number of bytes to copy + * @throws IndexOutOfBoundsException if an offset or size is negative or too + * large */ - public void copyTo(final byte[] target, final int sourceOffset, - final int targetOffset, - final int size) { - System.arraycopy(bytes, sourceOffset, target, targetOffset, size); + public void copyTo(byte[] target, int sourceOffset, int targetOffset, + int numberToCopy) { + if (sourceOffset < 0) { + throw new IndexOutOfBoundsException("Source offset < 0: " + sourceOffset); + } + if (targetOffset < 0) { + throw new IndexOutOfBoundsException("Target offset < 0: " + targetOffset); + } + if (numberToCopy < 0) { + throw new IndexOutOfBoundsException("Length < 0: " + numberToCopy); + } + if (sourceOffset + numberToCopy > size()) { + throw new IndexOutOfBoundsException( + "Source end offset < 0: " + (sourceOffset + numberToCopy)); + } + if (targetOffset + numberToCopy > target.length) { + throw new IndexOutOfBoundsException( + "Target end offset < 0: " + (targetOffset + numberToCopy)); + } + if (numberToCopy > 0) { + copyToInternal(target, sourceOffset, targetOffset, numberToCopy); + } } /** + * Internal (package private) implementation of + * @link{#copyTo(byte[],int,int,int}. + * It assumes that all error checking has already been performed and that + * @code{numberToCopy > 0}. + */ + protected abstract void copyToInternal(byte[] target, int sourceOffset, + int targetOffset, int numberToCopy); + + /** + * Copies bytes into a ByteBuffer. + * + * @param target ByteBuffer to copy into. + * @throws java.nio.ReadOnlyBufferException if the {@code target} is read-only + * @throws java.nio.BufferOverflowException if the {@code target}'s + * remaining() space is not large enough to hold the data. + */ + public abstract void copyTo(ByteBuffer target); + + /** * Copies bytes to a {@code byte[]}. + * + * @return copied bytes */ public byte[] toByteArray() { - final int size = bytes.length; - final byte[] copy = new byte[size]; - System.arraycopy(bytes, 0, copy, 0, size); - return copy; + int size = size(); + if (size == 0) { + return Internal.EMPTY_BYTE_ARRAY; + } + byte[] result = new byte[size]; + copyToInternal(result, 0, 0, size); + return result; } /** - * Constructs a new read-only {@code java.nio.ByteBuffer} with the - * same backing byte array. + * Writes the complete contents of this byte string to + * the specified output stream argument. + * + * @param out the output stream to which to write the data. + * @throws IOException if an I/O error occurs. */ - public ByteBuffer asReadOnlyByteBuffer() { - final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); - return byteBuffer.asReadOnlyBuffer(); + public abstract void writeTo(OutputStream out) throws IOException; + + /** + * Writes a specified part of this byte string to an output stream. + * + * @param out the output stream to which to write the data. + * @param sourceOffset offset within these bytes + * @param numberToWrite number of bytes to write + * @throws IOException if an I/O error occurs. + * @throws IndexOutOfBoundsException if an offset or size is negative or too + * large + */ + void writeTo(OutputStream out, int sourceOffset, int numberToWrite) + throws IOException { + if (sourceOffset < 0) { + throw new IndexOutOfBoundsException("Source offset < 0: " + sourceOffset); + } + if (numberToWrite < 0) { + throw new IndexOutOfBoundsException("Length < 0: " + numberToWrite); + } + if (sourceOffset + numberToWrite > size()) { + throw new IndexOutOfBoundsException( + "Source end offset exceeded: " + (sourceOffset + numberToWrite)); + } + if (numberToWrite > 0) { + writeToInternal(out, sourceOffset, numberToWrite); + } + } /** + * Internal version of {@link #writeTo(OutputStream,int,int)} that assumes + * all error checking has already been done. + */ + abstract void writeToInternal(OutputStream out, int sourceOffset, + int numberToWrite) throws IOException; + + /** + * Constructs a read-only {@code java.nio.ByteBuffer} whose content + * is equal to the contents of this byte string. + * The result uses the same backing array as the byte string, if possible. + * + * @return wrapped bytes + */ + public abstract ByteBuffer asReadOnlyByteBuffer(); + + /** + * Constructs a list of read-only {@code java.nio.ByteBuffer} objects + * such that the concatenation of their contents is equal to the contents + * of this byte string. The result uses the same backing arrays as the + * byte string. + *

+ * By returning a list, implementations of this method may be able to avoid + * copying even when there are multiple backing arrays. + * + * @return a list of wrapped bytes + */ + public abstract List asReadOnlyByteBufferList(); + + /** * Constructs a new {@code String} by decoding the bytes using the * specified charset. + * + * @param charsetName encode using this charset + * @return new string + * @throws UnsupportedEncodingException if charset isn't recognized */ - public String toString(final String charsetName) - throws UnsupportedEncodingException { - return new String(bytes, charsetName); - } + public abstract String toString(String charsetName) + throws UnsupportedEncodingException; + + // ================================================================= + // UTF-8 decoding /** * Constructs a new {@code String} by decoding the bytes as UTF-8. + * + * @return new string using UTF-8 encoding */ public String toStringUtf8() { try { - return new String(bytes, "UTF-8"); + return toString("UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException("UTF-8 not supported?", e); } } + /** + * Tells whether this {@code ByteString} represents a well-formed UTF-8 + * byte sequence, such that the original bytes can be converted to a + * String object and then round tripped back to bytes without loss. + * + *

More precisely, returns {@code true} whenever:

 {@code
+   * Arrays.equals(byteString.toByteArray(),
+   *     new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
+   * }
+ * + *

This method returns {@code false} for "overlong" byte sequences, + * as well as for 3-byte sequences that would map to a surrogate + * character, in accordance with the restricted definition of UTF-8 + * introduced in Unicode 3.1. Note that the UTF-8 decoder included in + * Oracle's JDK has been modified to also reject "overlong" byte + * sequences, but (as of 2011) still accepts 3-byte surrogate + * character byte sequences. + * + *

See the Unicode Standard,
+ * Table 3-6. UTF-8 Bit Distribution,
+ * Table 3-7. Well Formed UTF-8 Byte Sequences. + * + * @return whether the bytes in this {@code ByteString} are a + * well-formed UTF-8 byte sequence + */ + public abstract boolean isValidUtf8(); + + /** + * Tells whether the given byte sequence is a well-formed, malformed, or + * incomplete UTF-8 byte sequence. This method accepts and returns a partial + * state result, allowing the bytes for a complete UTF-8 byte sequence to be + * composed from multiple {@code ByteString} segments. + * + * @param state either {@code 0} (if this is the initial decoding operation) + * or the value returned from a call to a partial decoding method for the + * previous bytes + * @param offset offset of the first byte to check + * @param length number of bytes to check + * + * @return {@code -1} if the partial byte sequence is definitely malformed, + * {@code 0} if it is well-formed (no additional input needed), or, if the + * byte sequence is "incomplete", i.e. apparently terminated in the middle of + * a character, an opaque integer "state" value containing enough information + * to decode the character when passed to a subsequent invocation of a + * partial decoding method. + */ + protected abstract int partialIsValidUtf8(int state, int offset, int length); + // ================================================================= // equals() and hashCode() @Override - public boolean equals(final Object o) { - if (o == this) { - return true; - } - - if (!(o instanceof ByteString)) { - return false; - } - - final ByteString other = (ByteString) o; - final int size = bytes.length; - if (size != other.bytes.length) { - return false; - } - - final byte[] thisBytes = bytes; - final byte[] otherBytes = other.bytes; - for (int i = 0; i < size; i++) { - if (thisBytes[i] != otherBytes[i]) { - return false; - } - } - - return true; - } - - private volatile int hash = 0; + public abstract boolean equals(Object o); + /** + * Return a non-zero hashCode depending only on the sequence of bytes + * in this ByteString. + * + * @return hashCode value for this object + */ @Override - public int hashCode() { - int h = hash; - - if (h == 0) { - final byte[] thisBytes = bytes; - final int size = bytes.length; - - h = size; - for (int i = 0; i < size; i++) { - h = h * 31 + thisBytes[i]; - } - if (h == 0) { - h = 1; - } - - hash = h; - } - - return h; - } + public abstract int hashCode(); // ================================================================= // Input stream /** * Creates an {@code InputStream} which can be used to read the bytes. + *

+ * The {@link InputStream} returned by this method is guaranteed to be + * completely non-blocking. The method {@link InputStream#available()} + * returns the number of bytes remaining in the stream. The methods + * {@link InputStream#read(byte[]), {@link InputStream#read(byte[],int,int)} + * and {@link InputStream#skip(long)} will read/skip as many bytes as are + * available. + *

+ * The methods in the returned {@link InputStream} might not be + * thread safe. + * + * @return an input stream that returns the bytes of this byte string. */ - public InputStream newInput() { - return new ByteArrayInputStream(bytes); - } + public abstract InputStream newInput(); /** * Creates a {@link CodedInputStream} which can be used to read the bytes. - * Using this is more efficient than creating a {@link CodedInputStream} - * wrapping the result of {@link #newInput()}. + * Using this is often more efficient than creating a {@link CodedInputStream} + * that wraps the result of {@link #newInput()}. + * + * @return stream based on wrapped data */ - public CodedInputStream newCodedInput() { - // We trust CodedInputStream not to modify the bytes, or to give anyone - // else access to them. - return CodedInputStream.newInstance(bytes); - } + public abstract CodedInputStream newCodedInput(); // ================================================================= // Output stream /** - * Creates a new {@link Output} with the given initial capacity. + * Creates a new {@link Output} with the given initial capacity. Call {@link + * Output#toByteString()} to create the {@code ByteString} instance. + *

+ * A {@link ByteString.Output} offers the same functionality as a + * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString} + * rather than a {@code byte} array. + * + * @param initialCapacity estimate of number of bytes to be written + * @return {@code OutputStream} for building a {@code ByteString} */ - public static Output newOutput(final int initialCapacity) { - return new Output(new ByteArrayOutputStream(initialCapacity)); + public static Output newOutput(int initialCapacity) { + return new Output(initialCapacity); } /** - * Creates a new {@link Output}. + * Creates a new {@link Output}. Call {@link Output#toByteString()} to create + * the {@code ByteString} instance. + *

+ * A {@link ByteString.Output} offers the same functionality as a + * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString} + * rather than a {@code byte array}. + * + * @return {@code OutputStream} for building a {@code ByteString} */ public static Output newOutput() { - return newOutput(32); + return new Output(CONCATENATE_BY_COPY_SIZE); } /** * Outputs to a {@code ByteString} instance. Call {@link #toByteString()} to * create the {@code ByteString} instance. */ - public static final class Output extends FilterOutputStream { - private final ByteArrayOutputStream bout; + public static final class Output extends OutputStream { + // Implementation note. + // The public methods of this class must be synchronized. ByteStrings + // are guaranteed to be immutable. Without some sort of locking, it could + // be possible for one thread to call toByteSring(), while another thread + // is still modifying the underlying byte array. + + private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + // argument passed by user, indicating initial capacity. + private final int initialCapacity; + // ByteStrings to be concatenated to create the result + private final ArrayList flushedBuffers; + // Total number of bytes in the ByteStrings of flushedBuffers + private int flushedBuffersTotalBytes; + // Current buffer to which we are writing + private byte[] buffer; + // Location in buffer[] to which we write the next byte. + private int bufferPos; /** - * Constructs a new output with the given initial capacity. + * Creates a new ByteString output stream with the specified + * initial capacity. + * + * @param initialCapacity the initial capacity of the output stream. */ - private Output(final ByteArrayOutputStream bout) { - super(bout); - this.bout = bout; + Output(int initialCapacity) { + if (initialCapacity < 0) { + throw new IllegalArgumentException("Buffer size < 0"); + } + this.initialCapacity = initialCapacity; + this.flushedBuffers = new ArrayList(); + this.buffer = new byte[initialCapacity]; + } + + @Override + public synchronized void write(int b) { + if (bufferPos == buffer.length) { + flushFullBuffer(1); + } + buffer[bufferPos++] = (byte)b; + } + + @Override + public synchronized void write(byte[] b, int offset, int length) { + if (length <= buffer.length - bufferPos) { + // The bytes can fit into the current buffer. + System.arraycopy(b, offset, buffer, bufferPos, length); + bufferPos += length; + } else { + // Use up the current buffer + int copySize = buffer.length - bufferPos; + System.arraycopy(b, offset, buffer, bufferPos, copySize); + offset += copySize; + length -= copySize; + // Flush the buffer, and get a new buffer at least big enough to cover + // what we still need to output + flushFullBuffer(length); + System.arraycopy(b, offset, buffer, 0 /* count */, length); + bufferPos = length; + } } /** - * Creates a {@code ByteString} instance from this {@code Output}. + * Creates a byte string. Its size is the current size of this output + * stream and its output has been copied to it. + * + * @return the current contents of this output stream, as a byte string. */ - public ByteString toByteString() { - final byte[] byteArray = bout.toByteArray(); - return new ByteString(byteArray); + public synchronized ByteString toByteString() { + flushLastBuffer(); + return ByteString.copyFrom(flushedBuffers); + } + + /** + * Implement java.util.Arrays.copyOf() for jdk 1.5. + */ + private byte[] copyArray(byte[] buffer, int length) { + byte[] result = new byte[length]; + System.arraycopy(buffer, 0, result, 0, Math.min(buffer.length, length)); + return result; + } + + /** + * Writes the complete contents of this byte array output stream to + * the specified output stream argument. + * + * @param out the output stream to which to write the data. + * @throws IOException if an I/O error occurs. + */ + public void writeTo(OutputStream out) throws IOException { + ByteString[] cachedFlushBuffers; + byte[] cachedBuffer; + int cachedBufferPos; + synchronized (this) { + // Copy the information we need into local variables so as to hold + // the lock for as short a time as possible. + cachedFlushBuffers = + flushedBuffers.toArray(new ByteString[flushedBuffers.size()]); + cachedBuffer = buffer; + cachedBufferPos = bufferPos; + } + for (ByteString byteString : cachedFlushBuffers) { + byteString.writeTo(out); + } + + out.write(copyArray(cachedBuffer, cachedBufferPos)); + } + + /** + * Returns the current size of the output stream. + * + * @return the current size of the output stream + */ + public synchronized int size() { + return flushedBuffersTotalBytes + bufferPos; + } + + /** + * Resets this stream, so that all currently accumulated output in the + * output stream is discarded. The output stream can be used again, + * reusing the already allocated buffer space. + */ + public synchronized void reset() { + flushedBuffers.clear(); + flushedBuffersTotalBytes = 0; + bufferPos = 0; + } + + @Override + public String toString() { + return String.format("", + Integer.toHexString(System.identityHashCode(this)), size()); + } + + /** + * Internal function used by writers. The current buffer is full, and the + * writer needs a new buffer whose size is at least the specified minimum + * size. + */ + private void flushFullBuffer(int minSize) { + flushedBuffers.add(new LiteralByteString(buffer)); + flushedBuffersTotalBytes += buffer.length; + // We want to increase our total capacity by 50%, but as a minimum, + // the new buffer should also at least be >= minSize and + // >= initial Capacity. + int newSize = Math.max(initialCapacity, + Math.max(minSize, flushedBuffersTotalBytes >>> 1)); + buffer = new byte[newSize]; + bufferPos = 0; + } + + /** + * Internal function used by {@link #toByteString()}. The current buffer may + * or may not be full, but it needs to be flushed. + */ + private void flushLastBuffer() { + if (bufferPos < buffer.length) { + if (bufferPos > 0) { + byte[] bufferCopy = copyArray(buffer, bufferPos); + flushedBuffers.add(new LiteralByteString(bufferCopy)); + } + // We reuse this buffer for further writes. + } else { + // Buffer is completely full. Huzzah. + flushedBuffers.add(new LiteralByteString(buffer)); + // 99% of the time, we're not going to use this OutputStream again. + // We set buffer to an empty byte stream so that we're handling this + // case without wasting space. In the rare case that more writes + // *do* occur, this empty buffer will be flushed and an appropriately + // sized new buffer will be created. + buffer = EMPTY_BYTE_ARRAY; + } + flushedBuffersTotalBytes += bufferPos; + bufferPos = 0; } } /** - * Constructs a new ByteString builder, which allows you to efficiently - * construct a {@code ByteString} by writing to a {@link CodedOutputStream}. - * Using this is much more efficient than calling {@code newOutput()} and - * wrapping that in a {@code CodedOutputStream}. + * Constructs a new {@code ByteString} builder, which allows you to + * efficiently construct a {@code ByteString} by writing to a {@link + * CodedOutputStream}. Using this is much more efficient than calling {@code + * newOutput()} and wrapping that in a {@code CodedOutputStream}. * *

This is package-private because it's a somewhat confusing interface. * Users can call {@link Message#toByteString()} instead of calling this * directly. * - * @param size The target byte size of the {@code ByteString}. You must - * write exactly this many bytes before building the result. + * @param size The target byte size of the {@code ByteString}. You must write + * exactly this many bytes before building the result. + * @return the builder */ - static CodedBuilder newCodedBuilder(final int size) { + static CodedBuilder newCodedBuilder(int size) { return new CodedBuilder(size); } @@ -370,7 +955,7 @@ public final class ByteString { private final CodedOutputStream output; private final byte[] buffer; - private CodedBuilder(final int size) { + private CodedBuilder(int size) { buffer = new byte[size]; output = CodedOutputStream.newInstance(buffer); } @@ -381,11 +966,57 @@ public final class ByteString { // We can be confident that the CodedOutputStream will not modify the // underlying bytes anymore because it already wrote all of them. So, // no need to make a copy. - return new ByteString(buffer); + return new LiteralByteString(buffer); } public CodedOutputStream getCodedOutput() { return output; } } + + // ================================================================= + // Methods {@link RopeByteString} needs on instances, which aren't part of the + // public API. + + /** + * Return the depth of the tree representing this {@code ByteString}, if any, + * whose root is this node. If this is a leaf node, return 0. + * + * @return tree depth or zero + */ + protected abstract int getTreeDepth(); + + /** + * Return {@code true} if this ByteString is literal (a leaf node) or a + * flat-enough tree in the sense of {@link RopeByteString}. + * + * @return true if the tree is flat enough + */ + protected abstract boolean isBalanced(); + + /** + * Return the cached hash code if available. + * + * @return value of cached hash code or 0 if not computed yet + */ + protected abstract int peekCachedHashCode(); + + /** + * Compute the hash across the value bytes starting with the given hash, and + * return the result. This is used to compute the hash across strings + * represented as a set of pieces by allowing the hash computation to be + * continued from piece to piece. + * + * @param h starting hash value + * @param offset offset into this value to start looking at data values + * @param length number of data values to include in the hash computation + * @return ending hash value + */ + protected abstract int partialHash(int h, int offset, int length); + + @Override + public String toString() { + return String.format("", + Integer.toHexString(System.identityHashCode(this)), size()); + } } diff --git a/java/src/main/java/com/google/protobuf/CodedInputStream.java b/java/src/main/java/com/google/protobuf/CodedInputStream.java index 22995e9..b25b971 100644 --- a/java/src/main/java/com/google/protobuf/CodedInputStream.java +++ b/java/src/main/java/com/google/protobuf/CodedInputStream.java @@ -30,9 +30,12 @@ package com.google.protobuf; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -67,7 +70,72 @@ public final class CodedInputStream { */ public static CodedInputStream newInstance(final byte[] buf, final int off, final int len) { - return new CodedInputStream(buf, off, len); + CodedInputStream result = new CodedInputStream(buf, off, len); + try { + // Some uses of CodedInputStream can be more efficient if they know + // exactly how many bytes are available. By pushing the end point of the + // buffer as a limit, we allow them to get this information via + // getBytesUntilLimit(). Pushing a limit that we know is at the end of + // the stream can never hurt, since we can never past that point anyway. + result.pushLimit(len); + } catch (InvalidProtocolBufferException ex) { + // The only reason pushLimit() might throw an exception here is if len + // is negative. Normally pushLimit()'s parameter comes directly off the + // wire, so it's important to catch exceptions in case of corrupt or + // malicious data. However, in this case, we expect that len is not a + // user-supplied value, so we can assume that it being negative indicates + // a programming error. Therefore, throwing an unchecked exception is + // appropriate. + throw new IllegalArgumentException(ex); + } + return result; + } + + /** + * Create a new CodedInputStream wrapping the given ByteBuffer. The data + * starting from the ByteBuffer's current position to its limit will be read. + * The returned CodedInputStream may or may not share the underlying data + * in the ByteBuffer, therefore the ByteBuffer cannot be changed while the + * CodedInputStream is in use. + * Note that the ByteBuffer's position won't be changed by this function. + * Concurrent calls with the same ByteBuffer object are safe if no other + * thread is trying to alter the ByteBuffer's status. + */ + public static CodedInputStream newInstance(ByteBuffer buf) { + if (buf.hasArray()) { + return newInstance(buf.array(), buf.arrayOffset() + buf.position(), + buf.remaining()); + } else { + ByteBuffer temp = buf.duplicate(); + byte[] buffer = new byte[temp.remaining()]; + temp.get(buffer); + return newInstance(buffer); + } + } + + /** + * Create a new CodedInputStream wrapping a LiteralByteString. + */ + static CodedInputStream newInstance(LiteralByteString byteString) { + CodedInputStream result = new CodedInputStream(byteString); + try { + // Some uses of CodedInputStream can be more efficient if they know + // exactly how many bytes are available. By pushing the end point of the + // buffer as a limit, we allow them to get this information via + // getBytesUntilLimit(). Pushing a limit that we know is at the end of + // the stream can never hurt, since we can never past that point anyway. + result.pushLimit(byteString.size()); + } catch (InvalidProtocolBufferException ex) { + // The only reason pushLimit() might throw an exception here is if len + // is negative. Normally pushLimit()'s parameter comes directly off the + // wire, so it's important to catch exceptions in case of corrupt or + // malicious data. However, in this case, we expect that len is not a + // user-supplied value, so we can assume that it being negative indicates + // a programming error. Therefore, throwing an unchecked exception is + // appropriate. + throw new IllegalArgumentException(ex); + } + return result; } // ----------------------------------------------------------------- @@ -107,6 +175,10 @@ public final class CodedInputStream { } } + public int getLastTag() { + return lastTag; + } + /** * Reads and discards a single field, given its tag value. * @@ -116,10 +188,10 @@ public final class CodedInputStream { public boolean skipField(final int tag) throws IOException { switch (WireFormat.getTagWireType(tag)) { case WireFormat.WIRETYPE_VARINT: - readInt32(); + skipRawVarint(); return true; case WireFormat.WIRETYPE_FIXED64: - readRawLittleEndian64(); + skipRawBytes(8); return true; case WireFormat.WIRETYPE_LENGTH_DELIMITED: skipRawBytes(readRawVarint32()); @@ -133,7 +205,7 @@ public final class CodedInputStream { case WireFormat.WIRETYPE_END_GROUP: return false; case WireFormat.WIRETYPE_FIXED32: - readRawLittleEndian32(); + skipRawBytes(4); return true; default: throw InvalidProtocolBufferException.invalidWireType(); @@ -141,6 +213,57 @@ public final class CodedInputStream { } /** + * Reads a single field and writes it to output in wire format, + * given its tag value. + * + * @return {@code false} if the tag is an endgroup tag, in which case + * nothing is skipped. Otherwise, returns {@code true}. + */ + public boolean skipField(final int tag, final CodedOutputStream output) + throws IOException { + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: { + long value = readInt64(); + output.writeRawVarint32(tag); + output.writeUInt64NoTag(value); + return true; + } + case WireFormat.WIRETYPE_FIXED64: { + long value = readRawLittleEndian64(); + output.writeRawVarint32(tag); + output.writeFixed64NoTag(value); + return true; + } + case WireFormat.WIRETYPE_LENGTH_DELIMITED: { + ByteString value = readBytes(); + output.writeRawVarint32(tag); + output.writeBytesNoTag(value); + return true; + } + case WireFormat.WIRETYPE_START_GROUP: { + output.writeRawVarint32(tag); + skipMessage(output); + int endtag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), + WireFormat.WIRETYPE_END_GROUP); + checkLastTagWas(endtag); + output.writeRawVarint32(endtag); + return true; + } + case WireFormat.WIRETYPE_END_GROUP: { + return false; + } + case WireFormat.WIRETYPE_FIXED32: { + int value = readRawLittleEndian32(); + output.writeRawVarint32(tag); + output.writeFixed32NoTag(value); + return true; + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + + /** * Reads and discards an entire message. This will read either until EOF * or until an endgroup tag, whichever comes first. */ @@ -153,6 +276,51 @@ public final class CodedInputStream { } } + /** + * Reads an entire message and writes it to output in wire format. + * This will read either until EOF or until an endgroup tag, + * whichever comes first. + */ + public void skipMessage(CodedOutputStream output) throws IOException { + while (true) { + final int tag = readTag(); + if (tag == 0 || !skipField(tag, output)) { + return; + } + } + } + + /** + * Collects the bytes skipped and returns the data in a ByteBuffer. + */ + private class SkippedDataSink implements RefillCallback { + private int lastPos = bufferPos; + private ByteArrayOutputStream byteArrayStream; + + @Override + public void onRefill() { + if (byteArrayStream == null) { + byteArrayStream = new ByteArrayOutputStream(); + } + byteArrayStream.write(buffer, lastPos, bufferPos - lastPos); + lastPos = 0; + } + + /** + * Gets skipped data in a ByteBuffer. This method should only be + * called once. + */ + ByteBuffer getSkippedData() { + if (byteArrayStream == null) { + return ByteBuffer.wrap(buffer, lastPos, bufferPos - lastPos); + } else { + byteArrayStream.write(buffer, lastPos, bufferPos); + return ByteBuffer.wrap(byteArrayStream.toByteArray()); + } + } + } + + // ----------------------------------------------------------------- /** Read a {@code double} field value from the stream. */ @@ -192,10 +360,14 @@ public final class CodedInputStream { /** Read a {@code bool} field value from the stream. */ public boolean readBool() throws IOException { - return readRawVarint32() != 0; + return readRawVarint64() != 0; } - /** Read a {@code string} field value from the stream. */ + /** + * Read a {@code string} field value from the stream. + * If the stream contains malformed UTF-8, + * replace the offending bytes with the standard UTF-8 replacement character. + */ public String readString() throws IOException { final int size = readRawVarint32(); if (size <= (bufferSize - bufferPos) && size > 0) { @@ -204,10 +376,40 @@ public final class CodedInputStream { final String result = new String(buffer, bufferPos, size, "UTF-8"); bufferPos += size; return result; + } else if (size == 0) { + return ""; } else { // Slow path: Build a byte array first then copy it. - return new String(readRawBytes(size), "UTF-8"); + return new String(readRawBytesSlowPath(size), "UTF-8"); + } + } + + /** + * Read a {@code string} field value from the stream. + * If the stream contains malformed UTF-8, + * throw exception {@link InvalidProtocolBufferException}. + */ + public String readStringRequireUtf8() throws IOException { + final int size = readRawVarint32(); + final byte[] bytes; + int pos = bufferPos; + if (size <= (bufferSize - pos) && size > 0) { + // Fast path: We already have the bytes in a contiguous buffer, so + // just copy directly from it. + bytes = buffer; + bufferPos = pos + size; + } else if (size == 0) { + return ""; + } else { + // Slow path: Build a byte array first then copy it. + bytes = readRawBytesSlowPath(size); + pos = 0; + } + // TODO(martinrb): We could save a pass by validating while decoding. + if (!Utf8.isValidUtf8(bytes, pos, pos + size)) { + throw InvalidProtocolBufferException.invalidUtf8(); } + return new String(bytes, pos, size, "UTF-8"); } /** Read a {@code group} field value from the stream. */ @@ -225,6 +427,24 @@ public final class CodedInputStream { --recursionDepth; } + + /** Read a {@code group} field value from the stream. */ + public T readGroup( + final int fieldNumber, + final Parser parser, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + if (recursionDepth >= recursionLimit) { + throw InvalidProtocolBufferException.recursionLimitExceeded(); + } + ++recursionDepth; + T result = parser.parsePartialFrom(this, extensionRegistry); + checkLastTagWas( + WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); + --recursionDepth; + return result; + } + /** * Reads a {@code group} field value from the stream and merges it into the * given {@link UnknownFieldSet}. @@ -260,18 +480,80 @@ public final class CodedInputStream { popLimit(oldLimit); } + + /** Read an embedded message field value from the stream. */ + public T readMessage( + final Parser parser, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + int length = readRawVarint32(); + if (recursionDepth >= recursionLimit) { + throw InvalidProtocolBufferException.recursionLimitExceeded(); + } + final int oldLimit = pushLimit(length); + ++recursionDepth; + T result = parser.parsePartialFrom(this, extensionRegistry); + checkLastTagWas(0); + --recursionDepth; + popLimit(oldLimit); + return result; + } + /** Read a {@code bytes} field value from the stream. */ public ByteString readBytes() throws IOException { final int size = readRawVarint32(); if (size <= (bufferSize - bufferPos) && size > 0) { // Fast path: We already have the bytes in a contiguous buffer, so // just copy directly from it. - final ByteString result = ByteString.copyFrom(buffer, bufferPos, size); + final ByteString result = bufferIsImmutable && enableAliasing + ? new BoundedByteString(buffer, bufferPos, size) + : ByteString.copyFrom(buffer, bufferPos, size); bufferPos += size; return result; + } else if (size == 0) { + return ByteString.EMPTY; } else { // Slow path: Build a byte array first then copy it. - return ByteString.copyFrom(readRawBytes(size)); + return new LiteralByteString(readRawBytesSlowPath(size)); + } + } + + /** Read a {@code bytes} field value from the stream. */ + public byte[] readByteArray() throws IOException { + final int size = readRawVarint32(); + if (size <= (bufferSize - bufferPos) && size > 0) { + // Fast path: We already have the bytes in a contiguous buffer, so + // just copy directly from it. + final byte[] result = + Arrays.copyOfRange(buffer, bufferPos, bufferPos + size); + bufferPos += size; + return result; + } else { + // Slow path: Build a byte array first then copy it. + return readRawBytesSlowPath(size); + } + } + + /** Read a {@code bytes} field value from the stream. */ + public ByteBuffer readByteBuffer() throws IOException { + final int size = readRawVarint32(); + if (size <= (bufferSize - bufferPos) && size > 0) { + // Fast path: We already have the bytes in a contiguous buffer. + // When aliasing is enabled, we can return a ByteBuffer pointing directly + // into the underlying byte array without copy if the CodedInputStream is + // constructed from a byte array. If aliasing is disabled or the input is + // from an InputStream or ByteString, we have to make a copy of the bytes. + ByteBuffer result = input == null && !bufferIsImmutable && enableAliasing + ? ByteBuffer.wrap(buffer, bufferPos, size).slice() + : ByteBuffer.wrap(Arrays.copyOfRange( + buffer, bufferPos, bufferPos + size)); + bufferPos += size; + return result; + } else if (size == 0) { + return Internal.EMPTY_BYTE_BUFFER; + } else { + // Slow path: Build a byte array first then copy it. + return ByteBuffer.wrap(readRawBytesSlowPath(size)); } } @@ -315,37 +597,67 @@ public final class CodedInputStream { * upper bits. */ public int readRawVarint32() throws IOException { - byte tmp = readRawByte(); - if (tmp >= 0) { - return tmp; - } - int result = tmp & 0x7f; - if ((tmp = readRawByte()) >= 0) { - result |= tmp << 7; - } else { - result |= (tmp & 0x7f) << 7; - if ((tmp = readRawByte()) >= 0) { - result |= tmp << 14; + // See implementation notes for readRawVarint64 + fastpath: { + int pos = bufferPos; + + if (bufferSize == pos) { + break fastpath; + } + + final byte[] buffer = this.buffer; + int x; + if ((x = buffer[pos++]) >= 0) { + bufferPos = pos; + return x; + } else if (bufferSize - pos < 9) { + break fastpath; + } else if ((x ^= (buffer[pos++] << 7)) < 0L) { + x ^= (~0L << 7); + } else if ((x ^= (buffer[pos++] << 14)) >= 0L) { + x ^= (~0L << 7) ^ (~0L << 14); + } else if ((x ^= (buffer[pos++] << 21)) < 0L) { + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21); } else { - result |= (tmp & 0x7f) << 14; - if ((tmp = readRawByte()) >= 0) { - result |= tmp << 21; - } else { - result |= (tmp & 0x7f) << 21; - result |= (tmp = readRawByte()) << 28; - if (tmp < 0) { - // Discard upper 32 bits. - for (int i = 0; i < 5; i++) { - if (readRawByte() >= 0) { - return result; - } - } - throw InvalidProtocolBufferException.malformedVarint(); - } + int y = buffer[pos++]; + x ^= y << 28; + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28); + if (y < 0 && + buffer[pos++] < 0 && + buffer[pos++] < 0 && + buffer[pos++] < 0 && + buffer[pos++] < 0 && + buffer[pos++] < 0) { + break fastpath; // Will throw malformedVarint() } } + bufferPos = pos; + return x; } - return result; + return (int) readRawVarint64SlowPath(); + } + + private void skipRawVarint() throws IOException { + if (bufferSize - bufferPos >= 10) { + final byte[] buffer = this.buffer; + int pos = bufferPos; + for (int i = 0; i < 10; i++) { + if (buffer[pos++] >= 0) { + bufferPos = pos; + return; + } + } + } + skipRawVarintSlowPath(); + } + + private void skipRawVarintSlowPath() throws IOException { + for (int i = 0; i < 10; i++) { + if (readRawByte() >= 0) { + return; + } + } + throw InvalidProtocolBufferException.malformedVarint(); } /** @@ -368,8 +680,8 @@ public final class CodedInputStream { * has already read one byte. This allows the caller to determine if EOF * has been reached before attempting to read. */ - static int readRawVarint32(final int firstByte, - final InputStream input) throws IOException { + public static int readRawVarint32( + final int firstByte, final InputStream input) throws IOException { if ((firstByte & 0x80) == 0) { return firstByte; } @@ -401,49 +713,115 @@ public final class CodedInputStream { /** Read a raw Varint from the stream. */ public long readRawVarint64() throws IOException { - int shift = 0; + // Implementation notes: + // + // Optimized for one-byte values, expected to be common. + // The particular code below was selected from various candidates + // empirically, by winning VarintBenchmark. + // + // Sign extension of (signed) Java bytes is usually a nuisance, but + // we exploit it here to more easily obtain the sign of bytes read. + // Instead of cleaning up the sign extension bits by masking eagerly, + // we delay until we find the final (positive) byte, when we clear all + // accumulated bits with one xor. We depend on javac to constant fold. + fastpath: { + int pos = bufferPos; + + if (bufferSize == pos) { + break fastpath; + } + + final byte[] buffer = this.buffer; + long x; + int y; + if ((y = buffer[pos++]) >= 0) { + bufferPos = pos; + return y; + } else if (bufferSize - pos < 9) { + break fastpath; + } else if ((x = y ^ (buffer[pos++] << 7)) < 0L) { + x ^= (~0L << 7); + } else if ((x ^= (buffer[pos++] << 14)) >= 0L) { + x ^= (~0L << 7) ^ (~0L << 14); + } else if ((x ^= (buffer[pos++] << 21)) < 0L) { + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21); + } else if ((x ^= ((long) buffer[pos++] << 28)) >= 0L) { + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28); + } else if ((x ^= ((long) buffer[pos++] << 35)) < 0L) { + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35); + } else if ((x ^= ((long) buffer[pos++] << 42)) >= 0L) { + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42); + } else if ((x ^= ((long) buffer[pos++] << 49)) < 0L) { + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42) + ^ (~0L << 49); + } else { + x ^= ((long) buffer[pos++] << 56); + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42) + ^ (~0L << 49) ^ (~0L << 56); + if (x < 0L) { + if (buffer[pos++] < 0L) { + break fastpath; // Will throw malformedVarint() + } + } + } + bufferPos = pos; + return x; + } + return readRawVarint64SlowPath(); + } + + /** Variant of readRawVarint64 for when uncomfortably close to the limit. */ + /* Visible for testing */ + long readRawVarint64SlowPath() throws IOException { long result = 0; - while (shift < 64) { + for (int shift = 0; shift < 64; shift += 7) { final byte b = readRawByte(); - result |= (long)(b & 0x7F) << shift; + result |= (long) (b & 0x7F) << shift; if ((b & 0x80) == 0) { return result; } - shift += 7; } throw InvalidProtocolBufferException.malformedVarint(); } /** Read a 32-bit little-endian integer from the stream. */ public int readRawLittleEndian32() throws IOException { - final byte b1 = readRawByte(); - final byte b2 = readRawByte(); - final byte b3 = readRawByte(); - final byte b4 = readRawByte(); - return (((int)b1 & 0xff) ) | - (((int)b2 & 0xff) << 8) | - (((int)b3 & 0xff) << 16) | - (((int)b4 & 0xff) << 24); + int pos = bufferPos; + + // hand-inlined ensureAvailable(4); + if (bufferSize - pos < 4) { + refillBuffer(4); + pos = bufferPos; + } + + final byte[] buffer = this.buffer; + bufferPos = pos + 4; + return (((buffer[pos] & 0xff)) | + ((buffer[pos + 1] & 0xff) << 8) | + ((buffer[pos + 2] & 0xff) << 16) | + ((buffer[pos + 3] & 0xff) << 24)); } /** Read a 64-bit little-endian integer from the stream. */ public long readRawLittleEndian64() throws IOException { - final byte b1 = readRawByte(); - final byte b2 = readRawByte(); - final byte b3 = readRawByte(); - final byte b4 = readRawByte(); - final byte b5 = readRawByte(); - final byte b6 = readRawByte(); - final byte b7 = readRawByte(); - final byte b8 = readRawByte(); - return (((long)b1 & 0xff) ) | - (((long)b2 & 0xff) << 8) | - (((long)b3 & 0xff) << 16) | - (((long)b4 & 0xff) << 24) | - (((long)b5 & 0xff) << 32) | - (((long)b6 & 0xff) << 40) | - (((long)b7 & 0xff) << 48) | - (((long)b8 & 0xff) << 56); + int pos = bufferPos; + + // hand-inlined ensureAvailable(8); + if (bufferSize - pos < 8) { + refillBuffer(8); + pos = bufferPos; + } + + final byte[] buffer = this.buffer; + bufferPos = pos + 8; + return ((((long) buffer[pos] & 0xffL)) | + (((long) buffer[pos + 1] & 0xffL) << 8) | + (((long) buffer[pos + 2] & 0xffL) << 16) | + (((long) buffer[pos + 3] & 0xffL) << 24) | + (((long) buffer[pos + 4] & 0xffL) << 32) | + (((long) buffer[pos + 5] & 0xffL) << 40) | + (((long) buffer[pos + 6] & 0xffL) << 48) | + (((long) buffer[pos + 7] & 0xffL) << 56)); } /** @@ -477,11 +855,13 @@ public final class CodedInputStream { // ----------------------------------------------------------------- private final byte[] buffer; + private final boolean bufferIsImmutable; private int bufferSize; private int bufferSizeAfterLimit; private int bufferPos; private final InputStream input; private int lastTag; + private boolean enableAliasing = false; /** * The total number of bytes read before the current buffer. The total @@ -512,6 +892,7 @@ public final class CodedInputStream { bufferPos = off; totalBytesRetired = -off; input = null; + bufferIsImmutable = false; } private CodedInputStream(final InputStream input) { @@ -520,6 +901,20 @@ public final class CodedInputStream { bufferPos = 0; totalBytesRetired = 0; this.input = input; + bufferIsImmutable = false; + } + + private CodedInputStream(final LiteralByteString byteString) { + buffer = byteString.bytes; + bufferPos = byteString.getOffsetIntoBytes(); + bufferSize = bufferPos + byteString.size(); + totalBytesRetired = -bufferPos; + input = null; + bufferIsImmutable = true; + } + + public void enableAliasing(boolean enabled) { + this.enableAliasing = enabled; } /** @@ -581,7 +976,7 @@ public final class CodedInputStream { * refreshing its buffer. If you need to prevent reading past a certain * point in the underlying {@code InputStream} (e.g. because you expect it to * contain more data after the end of the message which you need to handle - * differently) then you must place a wrapper around you {@code InputStream} + * differently) then you must place a wrapper around your {@code InputStream} * which limits the amount of data that can be read from it. * * @return the old limit. @@ -643,7 +1038,7 @@ public final class CodedInputStream { * if the stream has reached a limit created using {@link #pushLimit(int)}. */ public boolean isAtEnd() throws IOException { - return bufferPos == bufferSize && !refillBuffer(false); + return bufferPos == bufferSize && !tryRefillBuffer(1); } /** @@ -654,53 +1049,93 @@ public final class CodedInputStream { return totalBytesRetired + bufferPos; } + private interface RefillCallback { + void onRefill(); + } + + private RefillCallback refillCallback = null; + + /** + * Ensures that at least {@code n} bytes are available in the buffer, reading + * more bytes from the input if necessary to make it so. Caller must ensure + * that the requested space is less than BUFFER_SIZE. + * + * @throws InvalidProtocolBufferException The end of the stream or the current + * limit was reached. + */ + private void ensureAvailable(int n) throws IOException { + if (bufferSize - bufferPos < n) { + refillBuffer(n); + } + } + + /** + * Reads more bytes from the input, making at least {@code n} bytes available + * in the buffer. Caller must ensure that the requested space is not yet + * available, and that the requested space is less than BUFFER_SIZE. + * + * @throws InvalidProtocolBufferException The end of the stream or the current + * limit was reached. + */ + private void refillBuffer(int n) throws IOException { + if (!tryRefillBuffer(n)) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + } + /** - * Called with {@code this.buffer} is empty to read more bytes from the - * input. If {@code mustSucceed} is true, refillBuffer() gurantees that - * either there will be at least one byte in the buffer when it returns - * or it will throw an exception. If {@code mustSucceed} is false, - * refillBuffer() returns false if no more bytes were available. + * Tries to read more bytes from the input, making at least {@code n} bytes + * available in the buffer. Caller must ensure that the requested space is + * not yet available, and that the requested space is less than BUFFER_SIZE. + * + * @return {@code true} if the bytes could be made available; {@code false} + * if the end of the stream or the current limit was reached. */ - private boolean refillBuffer(final boolean mustSucceed) throws IOException { - if (bufferPos < bufferSize) { + private boolean tryRefillBuffer(int n) throws IOException { + if (bufferPos + n <= bufferSize) { throw new IllegalStateException( - "refillBuffer() called when buffer wasn't empty."); + "refillBuffer() called when " + n + + " bytes were already available in buffer"); } - if (totalBytesRetired + bufferSize == currentLimit) { + if (totalBytesRetired + bufferPos + n > currentLimit) { // Oops, we hit a limit. - if (mustSucceed) { - throw InvalidProtocolBufferException.truncatedMessage(); - } else { - return false; - } + return false; } - totalBytesRetired += bufferSize; - - bufferPos = 0; - bufferSize = (input == null) ? -1 : input.read(buffer); - if (bufferSize == 0 || bufferSize < -1) { - throw new IllegalStateException( - "InputStream#read(byte[]) returned invalid result: " + bufferSize + - "\nThe InputStream implementation is buggy."); + if (refillCallback != null) { + refillCallback.onRefill(); } - if (bufferSize == -1) { - bufferSize = 0; - if (mustSucceed) { - throw InvalidProtocolBufferException.truncatedMessage(); - } else { - return false; + + if (input != null) { + int pos = bufferPos; + if (pos > 0) { + if (bufferSize > pos) { + System.arraycopy(buffer, pos, buffer, 0, bufferSize - pos); + } + totalBytesRetired += pos; + bufferSize -= pos; + bufferPos = 0; } - } else { - recomputeBufferSizeAfterLimit(); - final int totalBytesRead = - totalBytesRetired + bufferSize + bufferSizeAfterLimit; - if (totalBytesRead > sizeLimit || totalBytesRead < 0) { - throw InvalidProtocolBufferException.sizeLimitExceeded(); + + int bytesRead = input.read(buffer, bufferSize, buffer.length - bufferSize); + if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) { + throw new IllegalStateException( + "InputStream#read(byte[]) returned invalid result: " + bytesRead + + "\nThe InputStream implementation is buggy."); + } + if (bytesRead > 0) { + bufferSize += bytesRead; + // Integer-overflow-conscious check against sizeLimit + if (totalBytesRetired + n - sizeLimit > 0) { + throw InvalidProtocolBufferException.sizeLimitExceeded(); + } + recomputeBufferSizeAfterLimit(); + return (bufferSize >= n) ? true : tryRefillBuffer(n); } - return true; } + + return false; } /** @@ -711,7 +1146,7 @@ public final class CodedInputStream { */ public byte readRawByte() throws IOException { if (bufferPos == bufferSize) { - refillBuffer(true); + refillBuffer(1); } return buffer[bufferPos++]; } @@ -723,8 +1158,26 @@ public final class CodedInputStream { * limit was reached. */ public byte[] readRawBytes(final int size) throws IOException { - if (size < 0) { - throw InvalidProtocolBufferException.negativeSize(); + final int pos = bufferPos; + if (size <= (bufferSize - pos) && size > 0) { + bufferPos = pos + size; + return Arrays.copyOfRange(buffer, pos, pos + size); + } else { + return readRawBytesSlowPath(size); + } + } + + /** + * Exactly like readRawBytes, but caller must have already checked the fast + * path: (size <= (bufferSize - pos) && size > 0) + */ + private byte[] readRawBytesSlowPath(final int size) throws IOException { + if (size <= 0) { + if (size == 0) { + return Internal.EMPTY_BYTE_ARRAY; + } else { + throw InvalidProtocolBufferException.negativeSize(); + } } if (totalBytesRetired + bufferPos + size > currentLimit) { @@ -734,13 +1187,7 @@ public final class CodedInputStream { throw InvalidProtocolBufferException.truncatedMessage(); } - if (size <= bufferSize - bufferPos) { - // We have all the bytes we need already. - final byte[] bytes = new byte[size]; - System.arraycopy(buffer, bufferPos, bytes, 0, size); - bufferPos += size; - return bytes; - } else if (size < BUFFER_SIZE) { + if (size < BUFFER_SIZE) { // Reading more bytes than are in the buffer, but not an excessive number // of bytes. We can safely allocate the resulting array ahead of time. @@ -750,18 +1197,10 @@ public final class CodedInputStream { System.arraycopy(buffer, bufferPos, bytes, 0, pos); bufferPos = bufferSize; - // We want to use refillBuffer() and then copy from the buffer into our + // We want to refill the buffer and then copy from the buffer into our // byte array rather than reading directly into our byte array because // the input may be unbuffered. - refillBuffer(true); - - while (size - pos > bufferSize) { - System.arraycopy(buffer, 0, bytes, pos, bufferSize); - pos += bufferSize; - bufferPos = bufferSize; - refillBuffer(true); - } - + ensureAvailable(size - pos); System.arraycopy(buffer, 0, bytes, pos, size - pos); bufferPos = size - pos; @@ -830,6 +1269,19 @@ public final class CodedInputStream { * limit was reached. */ public void skipRawBytes(final int size) throws IOException { + if (size <= (bufferSize - bufferPos) && size >= 0) { + // We have all the bytes we need already. + bufferPos += size; + } else { + skipRawBytesSlowPath(size); + } + } + + /** + * Exactly like skipRawBytes, but caller must have already checked the fast + * path: (size <= (bufferSize - pos) && size >= 0) + */ + private void skipRawBytesSlowPath(final int size) throws IOException { if (size < 0) { throw InvalidProtocolBufferException.negativeSize(); } @@ -841,25 +1293,19 @@ public final class CodedInputStream { throw InvalidProtocolBufferException.truncatedMessage(); } - if (size <= bufferSize - bufferPos) { - // We have all the bytes we need already. - bufferPos += size; - } else { - // Skipping more bytes than are in the buffer. First skip what we have. - int pos = bufferSize - bufferPos; - totalBytesRetired += bufferSize; - bufferPos = 0; - bufferSize = 0; + // Skipping more bytes than are in the buffer. First skip what we have. + int pos = bufferSize - bufferPos; + bufferPos = bufferSize; - // Then skip directly from the InputStream for the rest. - while (pos < size) { - final int n = (input == null) ? -1 : (int) input.skip(size - pos); - if (n <= 0) { - throw InvalidProtocolBufferException.truncatedMessage(); - } - pos += n; - totalBytesRetired += n; - } + // Keep refilling the buffer until we get to the point we wanted to skip to. + // This has the side effect of ensuring the limits are updated correctly. + refillBuffer(1); + while (size - pos > bufferSize) { + pos += bufferSize; + bufferPos = bufferSize; + refillBuffer(1); } + + bufferPos = size - pos; } } diff --git a/java/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/src/main/java/com/google/protobuf/CodedOutputStream.java index 58dd150..0f23207 100644 --- a/java/src/main/java/com/google/protobuf/CodedOutputStream.java +++ b/java/src/main/java/com/google/protobuf/CodedOutputStream.java @@ -30,9 +30,10 @@ package com.google.protobuf; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; /** * Encodes and writes protocol message fields. @@ -52,6 +53,7 @@ public final class CodedOutputStream { private final byte[] buffer; private final int limit; private int position; + private int totalBytesWritten = 0; private final OutputStream output; @@ -128,6 +130,38 @@ public final class CodedOutputStream { return new CodedOutputStream(flatArray, offset, length); } + /** + * Create a new {@code CodedOutputStream} that writes to the given ByteBuffer. + */ + public static CodedOutputStream newInstance(ByteBuffer byteBuffer) { + return newInstance(byteBuffer, DEFAULT_BUFFER_SIZE); + } + + /** + * Create a new {@code CodedOutputStream} that writes to the given ByteBuffer. + */ + public static CodedOutputStream newInstance(ByteBuffer byteBuffer, + int bufferSize) { + return newInstance(new ByteBufferOutputStream(byteBuffer), bufferSize); + } + + private static class ByteBufferOutputStream extends OutputStream { + private final ByteBuffer byteBuffer; + public ByteBufferOutputStream(ByteBuffer byteBuffer) { + this.byteBuffer = byteBuffer; + } + + @Override + public void write(int b) throws IOException { + byteBuffer.put((byte) b); + } + + @Override + public void write(byte[] data, int offset, int length) throws IOException { + byteBuffer.put(data, offset, length); + } + } + // ----------------------------------------------------------------- /** Write a {@code double} field, including tag, to the stream. */ @@ -201,6 +235,7 @@ public final class CodedOutputStream { writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); } + /** * Write a group represented by an {@link UnknownFieldSet}. * @@ -221,6 +256,7 @@ public final class CodedOutputStream { writeMessageNoTag(value); } + /** Write a {@code bytes} field, including tag, to the stream. */ public void writeBytes(final int fieldNumber, final ByteString value) throws IOException { @@ -228,6 +264,39 @@ public final class CodedOutputStream { writeBytesNoTag(value); } + /** Write a {@code bytes} field, including tag, to the stream. */ + public void writeByteArray(final int fieldNumber, final byte[] value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeByteArrayNoTag(value); + } + + /** Write a {@code bytes} field, including tag, to the stream. */ + public void writeByteArray(final int fieldNumber, + final byte[] value, + final int offset, + final int length) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeByteArrayNoTag(value, offset, length); + } + + /** + * Write a {@code bytes} field, including tag, to the stream. + * This method will write all content of the ByteBuffer regardless of the + * current position and limit (i.e., the number of bytes to be written is + * value.capacity(), not value.remaining()). Furthermore, this method doesn't + * alter the state of the passed-in ByteBuffer. Its position, limit, mark, + * etc. will remain unchanged. If you only want to write the remaining bytes + * of a ByteBuffer, you can call + * {@code writeByteBuffer(fieldNumber, byteBuffer.slice())}. + */ + public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeByteBufferNoTag(value); + } + /** Write a {@code uint32} field, including tag, to the stream. */ public void writeUInt32(final int fieldNumber, final int value) throws IOException { @@ -361,6 +430,7 @@ public final class CodedOutputStream { value.writeTo(this); } + /** * Write a group represented by an {@link UnknownFieldSet}. * @@ -379,11 +449,39 @@ public final class CodedOutputStream { value.writeTo(this); } + /** Write a {@code bytes} field to the stream. */ public void writeBytesNoTag(final ByteString value) throws IOException { - final byte[] bytes = value.toByteArray(); - writeRawVarint32(bytes.length); - writeRawBytes(bytes); + writeRawVarint32(value.size()); + writeRawBytes(value); + } + + /** Write a {@code bytes} field to the stream. */ + public void writeByteArrayNoTag(final byte[] value) throws IOException { + writeRawVarint32(value.length); + writeRawBytes(value); + } + + /** Write a {@code bytes} field to the stream. */ + public void writeByteArrayNoTag(final byte[] value, + final int offset, + final int length) throws IOException { + writeRawVarint32(length); + writeRawBytes(value, offset, length); + } + + /** + * Write a {@code bytes} field to the stream. This method will write all + * content of the ByteBuffer regardless of the current position and limit + * (i.e., the number of bytes to be written is value.capacity(), not + * value.remaining()). Furthermore, this method doesn't alter the state of + * the passed-in ByteBuffer. Its position, limit, mark, etc. will remain + * unchanged. If you only want to write the remaining bytes of a ByteBuffer, + * you can call {@code writeByteBufferNoTag(byteBuffer.slice())}. + */ + public void writeByteBufferNoTag(final ByteBuffer value) throws IOException { + writeRawVarint32(value.capacity()); + writeRawBytes(value); } /** Write a {@code uint32} field to the stream. */ @@ -396,7 +494,7 @@ public final class CodedOutputStream { * for converting the enum value to its numeric value. */ public void writeEnumNoTag(final int value) throws IOException { - writeRawVarint32(value); + writeInt32NoTag(value); } /** Write an {@code sfixed32} field to the stream. */ @@ -541,6 +639,33 @@ public final class CodedOutputStream { /** * Compute the number of bytes that would be needed to encode a + * {@code bytes} field, including tag. + */ + public static int computeByteArraySize(final int fieldNumber, + final byte[] value) { + return computeTagSize(fieldNumber) + computeByteArraySizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code bytes} field, including tag. + */ + public static int computeByteBufferSize(final int fieldNumber, + final ByteBuffer value) { + return computeTagSize(fieldNumber) + computeByteBufferSizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * embedded message in lazy field, including tag. + */ + public static int computeLazyFieldSize(final int fieldNumber, + final LazyFieldLite value) { + return computeTagSize(fieldNumber) + computeLazyFieldSizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a * {@code uint32} field, including tag. */ public static int computeUInt32Size(final int fieldNumber, final int value) { @@ -614,6 +739,18 @@ public final class CodedOutputStream { computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value); } + /** + * Compute the number of bytes that would be needed to encode an + * lazily parsed MessageSet extension field to the stream. For + * historical reasons, the wire format differs from normal fields. + */ + public static int computeLazyFieldMessageSetExtensionSize( + final int fieldNumber, final LazyFieldLite value) { + return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 + + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) + + computeLazyFieldSize(WireFormat.MESSAGE_SET_MESSAGE, value); + } + // ----------------------------------------------------------------- /** @@ -730,6 +867,15 @@ public final class CodedOutputStream { } /** + * Compute the number of bytes that would be needed to encode an embedded + * message stored in lazy field. + */ + public static int computeLazyFieldSizeNoTag(final LazyFieldLite value) { + final int size = value.getSerializedSize(); + return computeRawVarint32Size(size) + size; + } + + /** * Compute the number of bytes that would be needed to encode a * {@code bytes} field. */ @@ -740,6 +886,22 @@ public final class CodedOutputStream { /** * Compute the number of bytes that would be needed to encode a + * {@code bytes} field. + */ + public static int computeByteArraySizeNoTag(final byte[] value) { + return computeRawVarint32Size(value.length) + value.length; + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code bytes} field. + */ + public static int computeByteBufferSizeNoTag(final ByteBuffer value) { + return computeRawVarint32Size(value.capacity()) + value.capacity(); + } + + /** + * Compute the number of bytes that would be needed to encode a * {@code uint32} field. */ public static int computeUInt32SizeNoTag(final int value) { @@ -751,7 +913,7 @@ public final class CodedOutputStream { * Caller is responsible for converting the enum value to its numeric value. */ public static int computeEnumSizeNoTag(final int value) { - return computeRawVarint32Size(value); + return computeInt32SizeNoTag(value); } /** @@ -856,6 +1018,15 @@ public final class CodedOutputStream { } } + /** + * Get the total number of bytes successfully written to this stream. The + * returned value is not guaranteed to be accurate if exceptions have been + * found in the middle of writing. + */ + public int getTotalBytesWritten() { + return totalBytesWritten; + } + /** Write a single byte. */ public void writeRawByte(final byte value) throws IOException { if (position == limit) { @@ -863,6 +1034,7 @@ public final class CodedOutputStream { } buffer[position++] = value; + ++totalBytesWritten; } /** Write a single byte, represented by an integer value. */ @@ -870,11 +1042,71 @@ public final class CodedOutputStream { writeRawByte((byte) value); } + /** Write a byte string. */ + public void writeRawBytes(final ByteString value) throws IOException { + writeRawBytes(value, 0, value.size()); + } + /** Write an array of bytes. */ public void writeRawBytes(final byte[] value) throws IOException { writeRawBytes(value, 0, value.length); } + /** + * Write a ByteBuffer. This method will write all content of the ByteBuffer + * regardless of the current position and limit (i.e., the number of bytes + * to be written is value.capacity(), not value.remaining()). Furthermore, + * this method doesn't alter the state of the passed-in ByteBuffer. Its + * position, limit, mark, etc. will remain unchanged. If you only want to + * write the remaining bytes of a ByteBuffer, you can call + * {@code writeRawBytes(byteBuffer.slice())}. + */ + public void writeRawBytes(final ByteBuffer value) throws IOException { + if (value.hasArray()) { + writeRawBytes(value.array(), value.arrayOffset(), value.capacity()); + } else { + ByteBuffer duplicated = value.duplicate(); + duplicated.clear(); + writeRawBytesInternal(duplicated); + } + } + + /** Write a ByteBuffer that isn't backed by an array. */ + private void writeRawBytesInternal(final ByteBuffer value) + throws IOException { + int length = value.remaining(); + if (limit - position >= length) { + // We have room in the current buffer. + value.get(buffer, position, length); + position += length; + totalBytesWritten += length; + } else { + // Write extends past current buffer. Fill the rest of this buffer and + // flush. + final int bytesWritten = limit - position; + value.get(buffer, position, bytesWritten); + length -= bytesWritten; + position = limit; + totalBytesWritten += bytesWritten; + refreshBuffer(); + + // Now deal with the rest. + // Since we have an output stream, this is our buffer + // and buffer offset == 0 + while (length > limit) { + // Copy data into the buffer before writing it to OutputStream. + // TODO(xiaofeng): Introduce ZeroCopyOutputStream to avoid this copy. + value.get(buffer, 0, limit); + output.write(buffer, 0, limit); + length -= limit; + totalBytesWritten += limit; + } + value.get(buffer, 0, length); + position = length; + totalBytesWritten += length; + } + } + /** Write part of an array of bytes. */ public void writeRawBytes(final byte[] value, int offset, int length) throws IOException { @@ -882,6 +1114,7 @@ public final class CodedOutputStream { // We have room in the current buffer. System.arraycopy(value, offset, buffer, position, length); position += length; + totalBytesWritten += length; } else { // Write extends past current buffer. Fill the rest of this buffer and // flush. @@ -890,6 +1123,7 @@ public final class CodedOutputStream { offset += bytesWritten; length -= bytesWritten; position = limit; + totalBytesWritten += bytesWritten; refreshBuffer(); // Now deal with the rest. @@ -903,6 +1137,40 @@ public final class CodedOutputStream { // Write is very big. Let's do it all at once. output.write(value, offset, length); } + totalBytesWritten += length; + } + } + + /** Write part of a byte string. */ + public void writeRawBytes(final ByteString value, int offset, int length) + throws IOException { + if (limit - position >= length) { + // We have room in the current buffer. + value.copyTo(buffer, offset, position, length); + position += length; + totalBytesWritten += length; + } else { + // Write extends past current buffer. Fill the rest of this buffer and + // flush. + final int bytesWritten = limit - position; + value.copyTo(buffer, offset, position, bytesWritten); + offset += bytesWritten; + length -= bytesWritten; + position = limit; + totalBytesWritten += bytesWritten; + refreshBuffer(); + + // Now deal with the rest. + // Since we have an output stream, this is our buffer + // and buffer offset == 0 + if (length <= limit) { + // Fits in new buffer. + value.copyTo(buffer, offset, 0, length); + position = length; + } else { + value.writeTo(output, offset, length); + } + totalBytesWritten += length; } } diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java index c5e9a04..98e5232 100644 --- a/java/src/main/java/com/google/protobuf/Descriptors.java +++ b/java/src/main/java/com/google/protobuf/Descriptors.java @@ -32,11 +32,15 @@ package com.google.protobuf; import com.google.protobuf.DescriptorProtos.*; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.logging.Logger; import java.io.UnsupportedEncodingException; /** @@ -46,6 +50,11 @@ import java.io.UnsupportedEncodingException; * its fields and other information about a type. You can get a message * type's descriptor by calling {@code MessageType.getDescriptor()}, or * (given a message object of the type) {@code message.getDescriptorForType()}. + * Furthermore, each message is associated with a {@link FileDescriptor} for + * a relevant {@code .proto} file. You can obtain it by calling + * {@code Descriptor.getFile()}. A {@link FileDescriptor} contains descriptors + * for all the messages defined in that file, and file descriptors for all the + * imported {@code .proto} files. * * Descriptors are built from DescriptorProtos, as defined in * {@code google/protobuf/descriptor.proto}. @@ -53,16 +62,27 @@ import java.io.UnsupportedEncodingException; * @author kenton@google.com Kenton Varda */ public final class Descriptors { + private static final Logger logger = + Logger.getLogger(Descriptors.class.getName()); /** * Describes a {@code .proto} file, including everything defined within. + * That includes, in particular, descriptors for all the messages and + * file descriptors for all other imported {@code .proto} files + * (dependencies). */ - public static final class FileDescriptor { + public static final class FileDescriptor extends GenericDescriptor { /** Convert the descriptor to its protocol message representation. */ public FileDescriptorProto toProto() { return proto; } /** Get the file name. */ public String getName() { return proto.getName(); } + /** Returns this object. */ + public FileDescriptor getFile() { return this; } + + /** Returns the same as getName(). */ + public String getFullName() { return proto.getName(); } + /** * Get the proto package name. This is the package name given by the * {@code package} statement in the {@code .proto} file, which differs @@ -98,6 +118,11 @@ public final class Descriptors { return Collections.unmodifiableList(Arrays.asList(dependencies)); } + /** Get a list of this file's public dependencies (public imports). */ + public List getPublicDependencies() { + return Collections.unmodifiableList(Arrays.asList(publicDependencies)); + } + /** * Find a message type in the file by name. Does not find nested types. * @@ -198,8 +223,7 @@ public final class Descriptors { * * @param proto The protocol message form of the FileDescriptor. * @param dependencies {@code FileDescriptor}s corresponding to all of - * the file's dependencies, in the exact order listed - * in {@code proto}. + * the file's dependencies. * @throws DescriptorValidationException {@code proto} is not a valid * descriptor. This can occur for a number of reasons, e.g. * because a field has an undefined type or because two messages @@ -208,7 +232,29 @@ public final class Descriptors { public static FileDescriptor buildFrom(final FileDescriptorProto proto, final FileDescriptor[] dependencies) throws DescriptorValidationException { - // Building decsriptors involves two steps: translating and linking. + return buildFrom(proto, dependencies, false); + } + + + /** + * Construct a {@code FileDescriptor}. + * + * @param proto The protocol message form of the FileDescriptor. + * @param dependencies {@code FileDescriptor}s corresponding to all of + * the file's dependencies. + * @param allowUnknownDependencies If true, non-exist dependenncies will be + * ignored and undefined message types will be replaced with a + * placeholder type. + * @throws DescriptorValidationException {@code proto} is not a valid + * descriptor. This can occur for a number of reasons, e.g. + * because a field has an undefined type or because two messages + * were defined with the same name. + */ + private static FileDescriptor buildFrom( + final FileDescriptorProto proto, final FileDescriptor[] dependencies, + final boolean allowUnknownDependencies) + throws DescriptorValidationException { + // Building descriptors involves two steps: translating and linking. // In the translation step (implemented by FileDescriptor's // constructor), we build an object tree mirroring the // FileDescriptorProto's tree and put all of the descriptors into the @@ -217,23 +263,10 @@ public final class Descriptors { // FieldDescriptor for an embedded message contains a pointer directly // to the Descriptor for that message's type. We also detect undefined // types in the linking step. - final DescriptorPool pool = new DescriptorPool(dependencies); - final FileDescriptor result = - new FileDescriptor(proto, dependencies, pool); - - if (dependencies.length != proto.getDependencyCount()) { - throw new DescriptorValidationException(result, - "Dependencies passed to FileDescriptor.buildFrom() don't match " + - "those listed in the FileDescriptorProto."); - } - for (int i = 0; i < proto.getDependencyCount(); i++) { - if (!dependencies[i].getName().equals(proto.getDependency(i))) { - throw new DescriptorValidationException(result, - "Dependencies passed to FileDescriptor.buildFrom() don't match " + - "those listed in the FileDescriptorProto."); - } - } - + final DescriptorPool pool = new DescriptorPool( + dependencies, allowUnknownDependencies); + final FileDescriptor result = new FileDescriptor( + proto, dependencies, pool, allowUnknownDependencies); result.crossLink(); return result; } @@ -281,7 +314,9 @@ public final class Descriptors { final FileDescriptor result; try { - result = buildFrom(proto, dependencies); + // When building descriptors for generated code, we allow unknown + // dependencies by default. + result = buildFrom(proto, dependencies, true); } catch (DescriptorValidationException e) { throw new IllegalArgumentException( "Invalid embedded descriptor for \"" + proto.getName() + "\".", e); @@ -305,16 +340,66 @@ public final class Descriptors { } /** + * This method is to be called by generated code only. It uses Java + * reflection to load the dependencies' descriptors. + */ + public static void internalBuildGeneratedFileFrom( + final String[] descriptorDataParts, + final Class descriptorOuterClass, + final String[] dependencies, + final String[] dependencyFileNames, + final InternalDescriptorAssigner descriptorAssigner) { + List descriptors = new ArrayList(); + for (int i = 0; i < dependencies.length; i++) { + try { + Class clazz = + descriptorOuterClass.getClassLoader().loadClass(dependencies[i]); + descriptors.add( + (FileDescriptor) clazz.getField("descriptor").get(null)); + } catch (Exception e) { + // We allow unknown dependencies by default. If a dependency cannot + // be found we only generate a warning. + logger.warning("Descriptors for \"" + dependencyFileNames[i] + + "\" can not be found."); + } + } + FileDescriptor[] descriptorArray = new FileDescriptor[descriptors.size()]; + descriptors.toArray(descriptorArray); + internalBuildGeneratedFileFrom( + descriptorDataParts, descriptorArray, descriptorAssigner); + } + + /** + * This method is to be called by generated code only. It is used to + * update the FileDescriptorProto associated with the descriptor by + * parsing it again with the given ExtensionRegistry. This is needed to + * recognize custom options. + */ + public static void internalUpdateFileDescriptor( + final FileDescriptor descriptor, + final ExtensionRegistry registry) { + ByteString bytes = descriptor.proto.toByteString(); + FileDescriptorProto proto; + try { + proto = FileDescriptorProto.parseFrom(bytes, registry); + } catch (InvalidProtocolBufferException e) { + throw new IllegalArgumentException( + "Failed to parse protocol buffer descriptor for generated code.", e); + } + descriptor.setProto(proto); + } + + /** * This class should be used by generated code only. When calling * {@link FileDescriptor#internalBuildGeneratedFileFrom}, the caller * provides a callback implementing this interface. The callback is called * after the FileDescriptor has been constructed, in order to assign all - * the global variales defined in the generated code which point at parts + * the global variables defined in the generated code which point at parts * of the FileDescriptor. The callback returns an ExtensionRegistry which * contains any extensions which might be used in the descriptor -- that * is, extensions of the various "Options" messages defined in * descriptor.proto. The callback may also return null to indicate that - * no extensions are used in the decsriptor. + * no extensions are used in the descriptor. */ public interface InternalDescriptorAssigner { ExtensionRegistry assignDescriptors(FileDescriptor root); @@ -326,15 +411,43 @@ public final class Descriptors { private final ServiceDescriptor[] services; private final FieldDescriptor[] extensions; private final FileDescriptor[] dependencies; + private final FileDescriptor[] publicDependencies; private final DescriptorPool pool; private FileDescriptor(final FileDescriptorProto proto, final FileDescriptor[] dependencies, - final DescriptorPool pool) + final DescriptorPool pool, + boolean allowUnknownDependencies) throws DescriptorValidationException { this.pool = pool; this.proto = proto; this.dependencies = dependencies.clone(); + HashMap nameToFileMap = + new HashMap(); + for (FileDescriptor file : dependencies) { + nameToFileMap.put(file.getName(), file); + } + List publicDependencies = new ArrayList(); + for (int i = 0; i < proto.getPublicDependencyCount(); i++) { + int index = proto.getPublicDependency(i); + if (index < 0 || index >= proto.getDependencyCount()) { + throw new DescriptorValidationException(this, + "Invalid public dependency index."); + } + String name = proto.getDependency(index); + FileDescriptor file = nameToFileMap.get(name); + if (file == null) { + if (!allowUnknownDependencies) { + throw new DescriptorValidationException(this, + "Invalid public dependency: " + name); + } + // Ignore unknown dependencies. + } else { + publicDependencies.add(file); + } + } + this.publicDependencies = new FileDescriptor[publicDependencies.size()]; + publicDependencies.toArray(this.publicDependencies); pool.addPackage(getPackage(), this); @@ -360,6 +473,27 @@ public final class Descriptors { proto.getExtension(i), this, null, i, true); } } + + /** + * Create a placeholder FileDescriptor for a message Descriptor. + */ + FileDescriptor(String packageName, Descriptor message) + throws DescriptorValidationException { + this.pool = new DescriptorPool(new FileDescriptor[0], true); + this.proto = FileDescriptorProto.newBuilder() + .setName(message.getFullName() + ".placeholder.proto") + .setPackage(packageName).addMessageType(message.toProto()).build(); + this.dependencies = new FileDescriptor[0]; + this.publicDependencies = new FileDescriptor[0]; + + messageTypes = new Descriptor[] {message}; + enumTypes = new EnumDescriptor[0]; + services = new ServiceDescriptor[0]; + extensions = new FieldDescriptor[0]; + + pool.addPackage(packageName, this); + pool.addSymbol(message); + } /** Look up and cross-link all field types, etc. */ private void crossLink() throws DescriptorValidationException { @@ -382,7 +516,7 @@ public final class Descriptors { * in the original. This method is needed for bootstrapping when a file * defines custom options. The options may be defined in the file itself, * so we can't actually parse them until we've constructed the descriptors, - * but to construct the decsriptors we have to have parsed the descriptor + * but to construct the descriptors we have to have parsed the descriptor * protos. So, we have to parse the descriptor protos a second time after * constructing the descriptors. */ @@ -410,7 +544,7 @@ public final class Descriptors { // ================================================================= /** Describes a message type. */ - public static final class Descriptor implements GenericDescriptor { + public static final class Descriptor extends GenericDescriptor { /** * Get the index of this descriptor within its parent. In other words, * given a {@link FileDescriptor} {@code file}, the following is true: @@ -459,6 +593,11 @@ public final class Descriptors { return Collections.unmodifiableList(Arrays.asList(fields)); } + /** Get a list of this message type's oneofs. */ + public List getOneofs() { + return Collections.unmodifiableList(Arrays.asList(oneofs)); + } + /** Get a list of this message type's extensions. */ public List getExtensions() { return Collections.unmodifiableList(Arrays.asList(extensions)); @@ -486,6 +625,14 @@ public final class Descriptors { } /** + * Indicates whether the message can be extended. That is, whether it has + * any "extensions x to y" ranges declared on it. + */ + public boolean isExtendable() { + return proto.getExtensionRangeList().size() != 0; + } + + /** * Finds a field by name. * @param name The unqualified name of the field (e.g. "foo"). * @return The field's descriptor, or {@code null} if not found. @@ -549,6 +696,33 @@ public final class Descriptors { private final EnumDescriptor[] enumTypes; private final FieldDescriptor[] fields; private final FieldDescriptor[] extensions; + private final OneofDescriptor[] oneofs; + + // Used to create a placeholder when the type cannot be found. + Descriptor(final String fullname) throws DescriptorValidationException { + String name = fullname; + String packageName = ""; + int pos = fullname.lastIndexOf('.'); + if (pos != -1) { + name = fullname.substring(pos + 1); + packageName = fullname.substring(0, pos); + } + this.index = 0; + this.proto = DescriptorProto.newBuilder().setName(name).addExtensionRange( + DescriptorProto.ExtensionRange.newBuilder().setStart(1) + .setEnd(536870912).build()).build(); + this.fullName = fullname; + this.containingType = null; + + this.nestedTypes = new Descriptor[0]; + this.enumTypes = new EnumDescriptor[0]; + this.fields = new FieldDescriptor[0]; + this.extensions = new FieldDescriptor[0]; + this.oneofs = new OneofDescriptor[0]; + + // Create a placeholder FileDescriptor to hold this message. + this.file = new FileDescriptor(packageName, this); + } private Descriptor(final DescriptorProto proto, final FileDescriptor file, @@ -561,6 +735,12 @@ public final class Descriptors { this.file = file; containingType = parent; + oneofs = new OneofDescriptor[proto.getOneofDeclCount()]; + for (int i = 0; i < proto.getOneofDeclCount(); i++) { + oneofs[i] = new OneofDescriptor( + proto.getOneofDecl(i), file, this, i); + } + nestedTypes = new Descriptor[proto.getNestedTypeCount()]; for (int i = 0; i < proto.getNestedTypeCount(); i++) { nestedTypes[i] = new Descriptor( @@ -585,6 +765,17 @@ public final class Descriptors { proto.getExtension(i), file, this, i, true); } + for (int i = 0; i < proto.getOneofDeclCount(); i++) { + oneofs[i].fields = new FieldDescriptor[oneofs[i].getFieldCount()]; + oneofs[i].fieldCount = 0; + } + for (int i = 0; i < proto.getFieldCount(); i++) { + OneofDescriptor oneofDescriptor = fields[i].getContainingOneof(); + if (oneofDescriptor != null) { + oneofDescriptor.fields[oneofDescriptor.fieldCount++] = fields[i]; + } + } + file.pool.addSymbol(this); } @@ -629,11 +820,12 @@ public final class Descriptors { /** Describes a field of a message type. */ public static final class FieldDescriptor - implements GenericDescriptor, Comparable, + extends GenericDescriptor + implements Comparable, FieldSet.FieldDescriptorLite { /** * Get the index of this descriptor within its parent. - * @see Descriptor#getIndex() + * @see Descriptors.Descriptor#getIndex() */ public int getIndex() { return index; } @@ -648,7 +840,7 @@ public final class Descriptors { /** * Get the field's fully-qualified name. - * @see Descriptor#getFullName() + * @see Descriptors.Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -673,6 +865,12 @@ public final class Descriptors { public WireFormat.FieldType getLiteType() { return table[type.ordinal()]; } + + /** For internal use only. */ + public boolean needsUtf8Check() { + return (type == Type.STRING) && (getFile().getOptions().getJavaStringCheckUtf8()); + } + // I'm pretty sure values() constructs a new array every time, since there // is nothing stopping the caller from mutating the array. Therefore we // make a static copy here. @@ -734,6 +932,9 @@ public final class Descriptors { */ public Descriptor getContainingType() { return containingType; } + /** Get the field's containing oneof. */ + public OneofDescriptor getContainingOneof() { return containingOneof; } + /** * For extensions defined nested within message types, gets the outer * type. Not valid for non-extension fields. For example, consider @@ -811,6 +1012,7 @@ public final class Descriptors { private Type type; private Descriptor containingType; private Descriptor messageType; + private OneofDescriptor containingOneof; private EnumDescriptor enumType; private Object defaultValue; @@ -919,12 +1121,31 @@ public final class Descriptors { } else { extensionScope = null; } + + if (proto.hasOneofIndex()) { + throw new DescriptorValidationException(this, + "FieldDescriptorProto.oneof_index set for extension field."); + } + containingOneof = null; } else { if (proto.hasExtendee()) { throw new DescriptorValidationException(this, "FieldDescriptorProto.extendee set for non-extension field."); } containingType = parent; + + if (proto.hasOneofIndex()) { + if (proto.getOneofIndex() < 0 || + proto.getOneofIndex() >= parent.toProto().getOneofDeclCount()) { + throw new DescriptorValidationException(this, + "FieldDescriptorProto.oneof_index is out of range for type " + + parent.getName()); + } + containingOneof = parent.getOneofs().get(proto.getOneofIndex()); + containingOneof.fieldCount++; + } else { + containingOneof = null; + } extensionScope = null; } @@ -935,7 +1156,8 @@ public final class Descriptors { private void crossLink() throws DescriptorValidationException { if (proto.hasExtendee()) { final GenericDescriptor extendee = - file.pool.lookupSymbol(proto.getExtendee(), this); + file.pool.lookupSymbol(proto.getExtendee(), this, + DescriptorPool.SearchFilter.TYPES_ONLY); if (!(extendee instanceof Descriptor)) { throw new DescriptorValidationException(this, '\"' + proto.getExtendee() + "\" is not a message type."); @@ -952,7 +1174,8 @@ public final class Descriptors { if (proto.hasTypeName()) { final GenericDescriptor typeDescriptor = - file.pool.lookupSymbol(proto.getTypeName(), this); + file.pool.lookupSymbol(proto.getTypeName(), this, + DescriptorPool.SearchFilter.TYPES_ONLY); if (!proto.hasType()) { // Choose field type based on symbol. @@ -1132,16 +1355,17 @@ public final class Descriptors { // down-cast and call mergeFrom directly. return ((Message.Builder) to).mergeFrom((Message) from); } + } // ================================================================= /** Describes an enum type. */ - public static final class EnumDescriptor - implements GenericDescriptor, Internal.EnumLiteMap { + public static final class EnumDescriptor extends GenericDescriptor + implements Internal.EnumLiteMap { /** * Get the index of this descriptor within its parent. - * @see Descriptor#getIndex() + * @see Descriptors.Descriptor#getIndex() */ public int getIndex() { return index; } @@ -1153,7 +1377,7 @@ public final class Descriptors { /** * Get the type's fully-qualified name. - * @see Descriptor#getFullName() + * @see Descriptors.Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -1174,7 +1398,7 @@ public final class Descriptors { /** * Find an enum value by name. * @param name The unqualified name of the value (e.g. "FOO"). - * @return the value's decsriptor, or {@code null} if not found. + * @return the value's descriptor, or {@code null} if not found. */ public EnumValueDescriptor findValueByName(final String name) { final GenericDescriptor result = @@ -1190,7 +1414,7 @@ public final class Descriptors { * Find an enum value by number. If multiple enum values have the same * number, this returns the first defined value with that number. * @param number The value's number. - * @return the value's decsriptor, or {@code null} if not found. + * @return the value's descriptor, or {@code null} if not found. */ public EnumValueDescriptor findValueByNumber(final int number) { return file.pool.enumValuesByNumber.get( @@ -1249,11 +1473,11 @@ public final class Descriptors { * with the same number after the first become aliases of the first. * However, they still have independent EnumValueDescriptors. */ - public static final class EnumValueDescriptor - implements GenericDescriptor, Internal.EnumLite { + public static final class EnumValueDescriptor extends GenericDescriptor + implements Internal.EnumLite { /** * Get the index of this descriptor within its parent. - * @see Descriptor#getIndex() + * @see Descriptors.Descriptor#getIndex() */ public int getIndex() { return index; } @@ -1265,10 +1489,13 @@ public final class Descriptors { /** Get the value's number. */ public int getNumber() { return proto.getNumber(); } + + @Override + public String toString() { return proto.getName(); } /** * Get the value's fully-qualified name. - * @see Descriptor#getFullName() + * @see Descriptors.Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -1314,7 +1541,7 @@ public final class Descriptors { // ================================================================= /** Describes a service type. */ - public static final class ServiceDescriptor implements GenericDescriptor { + public static final class ServiceDescriptor extends GenericDescriptor { /** * Get the index of this descriptor within its parent. * * @see Descriptors.Descriptor#getIndex() @@ -1329,7 +1556,7 @@ public final class Descriptors { /** * Get the type's fully-qualified name. - * @see Descriptor#getFullName() + * @see Descriptors.Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -1347,7 +1574,7 @@ public final class Descriptors { /** * Find a method by name. * @param name The unqualified name of the method (e.g. "Foo"). - * @return the method's decsriptor, or {@code null} if not found. + * @return the method's descriptor, or {@code null} if not found. */ public MethodDescriptor findMethodByName(final String name) { final GenericDescriptor result = @@ -1404,7 +1631,7 @@ public final class Descriptors { /** * Describes one method within a service type. */ - public static final class MethodDescriptor implements GenericDescriptor { + public static final class MethodDescriptor extends GenericDescriptor { /** * Get the index of this descriptor within its parent. * * @see Descriptors.Descriptor#getIndex() @@ -1419,7 +1646,7 @@ public final class Descriptors { /** * Get the method's fully-qualified name. - * @see Descriptor#getFullName() + * @see Descriptors.Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -1467,7 +1694,8 @@ public final class Descriptors { private void crossLink() throws DescriptorValidationException { final GenericDescriptor input = - file.pool.lookupSymbol(proto.getInputType(), this); + file.pool.lookupSymbol(proto.getInputType(), this, + DescriptorPool.SearchFilter.TYPES_ONLY); if (!(input instanceof Descriptor)) { throw new DescriptorValidationException(this, '\"' + proto.getInputType() + "\" is not a message type."); @@ -1475,7 +1703,8 @@ public final class Descriptors { inputType = (Descriptor)input; final GenericDescriptor output = - file.pool.lookupSymbol(proto.getOutputType(), this); + file.pool.lookupSymbol(proto.getOutputType(), this, + DescriptorPool.SearchFilter.TYPES_ONLY); if (!(output instanceof Descriptor)) { throw new DescriptorValidationException(this, '\"' + proto.getOutputType() + "\" is not a message type."); @@ -1506,14 +1735,18 @@ public final class Descriptors { // ================================================================= /** - * All descriptors except {@code FileDescriptor} implement this to make - * {@code DescriptorPool}'s life easier. + * All descriptors implement this to make it easier to implement tools like + * {@code DescriptorPool}.

+ * + * This class is public so that the methods it exposes can be called from + * outside of this package. However, it should only be subclassed from + * nested classes of Descriptors. */ - private interface GenericDescriptor { - Message toProto(); - String getName(); - String getFullName(); - FileDescriptor getFile(); + public abstract static class GenericDescriptor { + public abstract Message toProto(); + public abstract String getName(); + public abstract String getFullName(); + public abstract FileDescriptor getFile(); } /** @@ -1527,7 +1760,7 @@ public final class Descriptors { public String getProblemSymbolName() { return name; } /** - * Gets the the protocol message representation of the invalid descriptor. + * Gets the protocol message representation of the invalid descriptor. */ public Message getProblemProto() { return proto; } @@ -1582,14 +1815,24 @@ public final class Descriptors { * descriptors defined in a particular file. */ private static final class DescriptorPool { - DescriptorPool(final FileDescriptor[] dependencies) { - this.dependencies = new DescriptorPool[dependencies.length]; + + /** Defines what subclass of descriptors to search in the descriptor pool. + */ + enum SearchFilter { + TYPES_ONLY, AGGREGATES_ONLY, ALL_SYMBOLS + } + + DescriptorPool(final FileDescriptor[] dependencies, + boolean allowUnknownDependencies) { + this.dependencies = new HashSet(); + this.allowUnknownDependencies = allowUnknownDependencies; - for (int i = 0; i < dependencies.length; i++) { - this.dependencies[i] = dependencies[i].pool; + for (int i = 0; i < dependencies.length; i++) { + this.dependencies.add(dependencies[i]); + importPublicDependencies(dependencies[i]); } - for (final FileDescriptor dependency : dependencies) { + for (final FileDescriptor dependency : this.dependencies) { try { addPackage(dependency.getPackage(), dependency); } catch (DescriptorValidationException e) { @@ -1601,7 +1844,17 @@ public final class Descriptors { } } - private final DescriptorPool[] dependencies; + /** Find and put public dependencies of the file into dependencies set.*/ + private void importPublicDependencies(final FileDescriptor file) { + for (FileDescriptor dependency : file.getPublicDependencies()) { + if (dependencies.add(dependency)) { + importPublicDependencies(dependency); + } + } + } + + private final Set dependencies; + private boolean allowUnknownDependencies; private final Map descriptorsByName = new HashMap(); @@ -1612,39 +1865,83 @@ public final class Descriptors { /** Find a generic descriptor by fully-qualified name. */ GenericDescriptor findSymbol(final String fullName) { + return findSymbol(fullName, SearchFilter.ALL_SYMBOLS); + } + + /** Find a descriptor by fully-qualified name and given option to only + * search valid field type descriptors. + */ + GenericDescriptor findSymbol(final String fullName, + final SearchFilter filter) { GenericDescriptor result = descriptorsByName.get(fullName); if (result != null) { - return result; + if ((filter==SearchFilter.ALL_SYMBOLS) || + ((filter==SearchFilter.TYPES_ONLY) && isType(result)) || + ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) { + return result; + } } - for (final DescriptorPool dependency : dependencies) { - result = dependency.descriptorsByName.get(fullName); + for (final FileDescriptor dependency : dependencies) { + result = dependency.pool.descriptorsByName.get(fullName); if (result != null) { - return result; + if ((filter==SearchFilter.ALL_SYMBOLS) || + ((filter==SearchFilter.TYPES_ONLY) && isType(result)) || + ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) { + return result; + } } } return null; } + /** Checks if the descriptor is a valid type for a message field. */ + boolean isType(GenericDescriptor descriptor) { + return (descriptor instanceof Descriptor) || + (descriptor instanceof EnumDescriptor); + } + + /** Checks if the descriptor is a valid namespace type. */ + boolean isAggregate(GenericDescriptor descriptor) { + return (descriptor instanceof Descriptor) || + (descriptor instanceof EnumDescriptor) || + (descriptor instanceof PackageDescriptor) || + (descriptor instanceof ServiceDescriptor); + } + /** - * Look up a descriptor by name, relative to some other descriptor. + * Look up a type descriptor by name, relative to some other descriptor. * The name may be fully-qualified (with a leading '.'), * partially-qualified, or unqualified. C++-like name lookup semantics * are used to search for the matching descriptor. */ GenericDescriptor lookupSymbol(final String name, - final GenericDescriptor relativeTo) + final GenericDescriptor relativeTo, + final DescriptorPool.SearchFilter filter) throws DescriptorValidationException { // TODO(kenton): This could be optimized in a number of ways. GenericDescriptor result; + String fullname; if (name.startsWith(".")) { // Fully-qualified name. - result = findSymbol(name.substring(1)); + fullname = name.substring(1); + result = findSymbol(fullname, filter); } else { // If "name" is a compound identifier, we want to search for the // first component of it, then search within it for the rest. + // If name is something like "Foo.Bar.baz", and symbols named "Foo" are + // defined in multiple parent scopes, we only want to find "Bar.baz" in + // the innermost one. E.g., the following should produce an error: + // message Bar { message Baz {} } + // message Foo { + // message Bar { + // } + // optional Bar.Baz baz = 1; + // } + // So, we look for just "Foo" first, then look for "Bar.baz" within it + // if found. final int firstPartLength = name.indexOf('.'); final String firstPart; if (firstPartLength == -1) { @@ -1662,14 +1959,16 @@ public final class Descriptors { // Chop off the last component of the scope. final int dotpos = scopeToTry.lastIndexOf("."); if (dotpos == -1) { - result = findSymbol(name); + fullname = name; + result = findSymbol(name, filter); break; } else { scopeToTry.setLength(dotpos + 1); - // Append firstPart and try to find. + // Append firstPart and try to find scopeToTry.append(firstPart); - result = findSymbol(scopeToTry.toString()); + result = findSymbol(scopeToTry.toString(), + DescriptorPool.SearchFilter.AGGREGATES_ONLY); if (result != null) { if (firstPartLength != -1) { @@ -1678,8 +1977,9 @@ public final class Descriptors { // searching parent scopes. scopeToTry.setLength(dotpos + 1); scopeToTry.append(name); - result = findSymbol(scopeToTry.toString()); + result = findSymbol(scopeToTry.toString(), filter); } + fullname = scopeToTry.toString(); break; } @@ -1690,8 +1990,24 @@ public final class Descriptors { } if (result == null) { - throw new DescriptorValidationException(relativeTo, - '\"' + name + "\" is not defined."); + if (allowUnknownDependencies && filter == SearchFilter.TYPES_ONLY) { + logger.warning("The descriptor for message type \"" + name + + "\" can not be found and a placeholder is created for it"); + // We create a dummy message descriptor here regardless of the + // expected type. If the type should be message, this dummy + // descriptor will work well and if the type should be enum, a + // DescriptorValidationException will be thrown latter. In either + // case, the code works as expected: we allow unknown message types + // but not unknwon enum types. + result = new Descriptor(fullname); + // Add the placeholder file as a dependency so we can find the + // placeholder symbol when resolving other references. + this.dependencies.add(result.getFile()); + return result; + } else { + throw new DescriptorValidationException(relativeTo, + '\"' + name + "\" is not defined."); + } } else { return result; } @@ -1735,7 +2051,7 @@ public final class Descriptors { * just as placeholders so that someone cannot define, say, a message type * that has the same name as an existing package. */ - private static final class PackageDescriptor implements GenericDescriptor { + private static final class PackageDescriptor extends GenericDescriptor { public Message toProto() { return file.toProto(); } public String getName() { return name; } public String getFullName() { return fullName; } @@ -1809,7 +2125,7 @@ public final class Descriptors { /** * Adds a field to the fieldsByNumber table. Throws an exception if a - * field with hte same containing type and number already exists. + * field with the same containing type and number already exists. */ void addFieldByNumber(final FieldDescriptor field) throws DescriptorValidationException { @@ -1820,7 +2136,7 @@ public final class Descriptors { fieldsByNumber.put(key, old); throw new DescriptorValidationException(field, "Field number " + field.getNumber() + - "has already been used in \"" + + " has already been used in \"" + field.getContainingType().getFullName() + "\" by field \"" + old.getName() + "\"."); } @@ -1876,4 +2192,47 @@ public final class Descriptors { } } } + + /** Describes an oneof of a message type. */ + public static final class OneofDescriptor { + /** Get the index of this descriptor within its parent. */ + public int getIndex() { return index; } + + public String getName() { return proto.getName(); } + + public FileDescriptor getFile() { return file; } + + public String getFullName() { return fullName; } + + public Descriptor getContainingType() { return containingType; } + + public int getFieldCount() { return fieldCount; } + + public FieldDescriptor getField(int index) { + return fields[index]; + } + + private OneofDescriptor(final OneofDescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index) + throws DescriptorValidationException { + this.proto = proto; + fullName = computeFullName(file, parent, proto.getName()); + this.file = file; + this.index = index; + + containingType = parent; + fieldCount = 0; + } + + private final int index; + private OneofDescriptorProto proto; + private final String fullName; + private final FileDescriptor file; + + private Descriptor containingType; + private int fieldCount; + private FieldDescriptor[] fields; + } } diff --git a/java/src/main/java/com/google/protobuf/DynamicMessage.java b/java/src/main/java/com/google/protobuf/DynamicMessage.java index c106b66..cb44766 100644 --- a/java/src/main/java/com/google/protobuf/DynamicMessage.java +++ b/java/src/main/java/com/google/protobuf/DynamicMessage.java @@ -31,10 +31,13 @@ package com.google.protobuf; import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.OneofDescriptor; import java.io.InputStream; import java.io.IOException; +import java.util.Collections; import java.util.Map; /** @@ -46,16 +49,25 @@ import java.util.Map; public final class DynamicMessage extends AbstractMessage { private final Descriptor type; private final FieldSet fields; + private final FieldDescriptor[] oneofCases; private final UnknownFieldSet unknownFields; private int memoizedSize = -1; /** * Construct a {@code DynamicMessage} using the given {@code FieldSet}. + * oneofCases stores the FieldDescriptor for each oneof to indicate + * which field is set. Caller should make sure the array is immutable. + * + * This contructor is package private and will be used in + * {@code DynamicMutableMessage} to convert a mutable message to an immutable + * message. */ - private DynamicMessage(Descriptor type, FieldSet fields, - UnknownFieldSet unknownFields) { + DynamicMessage(Descriptor type, FieldSet fields, + FieldDescriptor[] oneofCases, + UnknownFieldSet unknownFields) { this.type = type; this.fields = fields; + this.oneofCases = oneofCases; this.unknownFields = unknownFields; } @@ -64,10 +76,14 @@ public final class DynamicMessage extends AbstractMessage { * given type. */ public static DynamicMessage getDefaultInstance(Descriptor type) { + int oneofDeclCount = type.toProto().getOneofDeclCount(); + FieldDescriptor[] oneofCases = new FieldDescriptor[oneofDeclCount]; return new DynamicMessage(type, FieldSet.emptySet(), + oneofCases, UnknownFieldSet.getDefaultInstance()); } + /** Parse a message of the given type from the given input stream. */ public static DynamicMessage parseFrom(Descriptor type, CodedInputStream input) @@ -151,6 +167,20 @@ public final class DynamicMessage extends AbstractMessage { return fields.getAllFields(); } + public boolean hasOneof(OneofDescriptor oneof) { + verifyOneofContainingType(oneof); + FieldDescriptor field = oneofCases[oneof.getIndex()]; + if (field == null) { + return false; + } + return true; + } + + public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) { + verifyOneofContainingType(oneof); + return oneofCases[oneof.getIndex()]; + } + public boolean hasField(FieldDescriptor field) { verifyContainingType(field); return fields.hasField(field); @@ -160,7 +190,9 @@ public final class DynamicMessage extends AbstractMessage { verifyContainingType(field); Object result = fields.getField(field); if (result == null) { - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + result = Collections.emptyList(); + } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { result = getDefaultInstance(field.getMessageType()); } else { result = field.getDefaultValue(); @@ -183,8 +215,8 @@ public final class DynamicMessage extends AbstractMessage { return unknownFields; } - private static boolean isInitialized(Descriptor type, - FieldSet fields) { + static boolean isInitialized(Descriptor type, + FieldSet fields) { // Check that all required fields are present. for (final FieldDescriptor field : type.getFields()) { if (field.isRequired()) { @@ -198,10 +230,12 @@ public final class DynamicMessage extends AbstractMessage { return fields.isInitialized(); } + @Override public boolean isInitialized() { return isInitialized(type, fields); } + @Override public void writeTo(CodedOutputStream output) throws IOException { if (type.getOptions().getMessageSetWireFormat()) { fields.writeMessageSetTo(output); @@ -212,6 +246,7 @@ public final class DynamicMessage extends AbstractMessage { } } + @Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; @@ -236,6 +271,26 @@ public final class DynamicMessage extends AbstractMessage { return newBuilderForType().mergeFrom(this); } + public Parser getParserForType() { + return new AbstractParser() { + public DynamicMessage parsePartialFrom( + CodedInputStream input, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + Builder builder = newBuilder(type); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (IOException e) { + throw new InvalidProtocolBufferException(e.getMessage()) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + } + /** Verifies that the field is a field of this message. */ private void verifyContainingType(FieldDescriptor field) { if (field.getContainingType() != type) { @@ -244,6 +299,14 @@ public final class DynamicMessage extends AbstractMessage { } } + /** Verifies that the oneof is an oneof of this message. */ + private void verifyOneofContainingType(OneofDescriptor oneof) { + if (oneof.getContainingType() != type) { + throw new IllegalArgumentException( + "OneofDescriptor does not match message type."); + } + } + // ================================================================= /** @@ -252,6 +315,7 @@ public final class DynamicMessage extends AbstractMessage { public static final class Builder extends AbstractMessage.Builder { private final Descriptor type; private FieldSet fields; + private final FieldDescriptor[] oneofCases; private UnknownFieldSet unknownFields; /** Construct a {@code Builder} for the given type. */ @@ -259,19 +323,24 @@ public final class DynamicMessage extends AbstractMessage { this.type = type; this.fields = FieldSet.newFieldSet(); this.unknownFields = UnknownFieldSet.getDefaultInstance(); + this.oneofCases = new FieldDescriptor[type.toProto().getOneofDeclCount()]; } // --------------------------------------------------------------- // Implementation of Message.Builder interface. + @Override public Builder clear() { - if (fields == null) { - throw new IllegalStateException("Cannot call clear() after build()."); + if (fields.isImmutable()) { + fields = FieldSet.newFieldSet(); + } else { + fields.clear(); } - fields.clear(); + unknownFields = UnknownFieldSet.getDefaultInstance(); return this; } + @Override public Builder mergeFrom(Message other) { if (other instanceof DynamicMessage) { // This should be somewhat faster than calling super.mergeFrom(). @@ -280,8 +349,20 @@ public final class DynamicMessage extends AbstractMessage { throw new IllegalArgumentException( "mergeFrom(Message) can only merge messages of the same type."); } + ensureIsMutable(); fields.mergeFrom(otherDynamicMessage.fields); mergeUnknownFields(otherDynamicMessage.unknownFields); + for (int i = 0; i < oneofCases.length; i++) { + if (oneofCases[i] == null) { + oneofCases[i] = otherDynamicMessage.oneofCases[i]; + } else { + if ((otherDynamicMessage.oneofCases[i] != null) + && (oneofCases[i] != otherDynamicMessage.oneofCases[i])) { + fields.clearField(oneofCases[i]); + oneofCases[i] = otherDynamicMessage.oneofCases[i]; + } + } + } return this; } else { return super.mergeFrom(other); @@ -289,10 +370,10 @@ public final class DynamicMessage extends AbstractMessage { } public DynamicMessage build() { - // If fields == null, we'll throw an appropriate exception later. - if (fields != null && !isInitialized()) { + if (!isInitialized()) { throw newUninitializedMessageException( - new DynamicMessage(type, fields, unknownFields)); + new DynamicMessage(type, fields, + java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields)); } return buildPartial(); } @@ -305,28 +386,27 @@ public final class DynamicMessage extends AbstractMessage { private DynamicMessage buildParsed() throws InvalidProtocolBufferException { if (!isInitialized()) { throw newUninitializedMessageException( - new DynamicMessage(type, fields, unknownFields)) + new DynamicMessage(type, fields, + java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields)) .asInvalidProtocolBufferException(); } return buildPartial(); } public DynamicMessage buildPartial() { - if (fields == null) { - throw new IllegalStateException( - "build() has already been called on this Builder."); - } fields.makeImmutable(); DynamicMessage result = - new DynamicMessage(type, fields, unknownFields); - fields = null; - unknownFields = null; + new DynamicMessage(type, fields, + java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields); return result; } + @Override public Builder clone() { Builder result = new Builder(type); result.fields.mergeFrom(fields); + result.mergeUnknownFields(unknownFields); + System.arraycopy(oneofCases, 0, result.oneofCases, 0 , oneofCases.length); return result; } @@ -357,6 +437,29 @@ public final class DynamicMessage extends AbstractMessage { return new Builder(field.getMessageType()); } + public boolean hasOneof(OneofDescriptor oneof) { + verifyOneofContainingType(oneof); + FieldDescriptor field = oneofCases[oneof.getIndex()]; + if (field == null) { + return false; + } + return true; + } + + public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) { + verifyOneofContainingType(oneof); + return oneofCases[oneof.getIndex()]; + } + + public Builder clearOneof(OneofDescriptor oneof) { + verifyOneofContainingType(oneof); + FieldDescriptor field = oneofCases[oneof.getIndex()]; + if (field != null) { + clearField(field); + } + return this; + } + public boolean hasField(FieldDescriptor field) { verifyContainingType(field); return fields.hasField(field); @@ -366,7 +469,9 @@ public final class DynamicMessage extends AbstractMessage { verifyContainingType(field); Object result = fields.getField(field); if (result == null) { - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + result = Collections.emptyList(); + } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { result = getDefaultInstance(field.getMessageType()); } else { result = field.getDefaultValue(); @@ -377,12 +482,33 @@ public final class DynamicMessage extends AbstractMessage { public Builder setField(FieldDescriptor field, Object value) { verifyContainingType(field); + ensureIsMutable(); + if (field.getType() == FieldDescriptor.Type.ENUM) { + verifyEnumType(field, value); + } + OneofDescriptor oneofDescriptor = field.getContainingOneof(); + if (oneofDescriptor != null) { + int index = oneofDescriptor.getIndex(); + FieldDescriptor oldField = oneofCases[index]; + if ((oldField != null) && (oldField != field)) { + fields.clearField(oldField); + } + oneofCases[index] = field; + } fields.setField(field, value); return this; } public Builder clearField(FieldDescriptor field) { verifyContainingType(field); + ensureIsMutable(); + OneofDescriptor oneofDescriptor = field.getContainingOneof(); + if (oneofDescriptor != null) { + int index = oneofDescriptor.getIndex(); + if (oneofCases[index] == field) { + oneofCases[index] = null; + } + } fields.clearField(field); return this; } @@ -400,12 +526,14 @@ public final class DynamicMessage extends AbstractMessage { public Builder setRepeatedField(FieldDescriptor field, int index, Object value) { verifyContainingType(field); + ensureIsMutable(); fields.setRepeatedField(field, index, value); return this; } public Builder addRepeatedField(FieldDescriptor field, Object value) { verifyContainingType(field); + ensureIsMutable(); fields.addRepeatedField(field, value); return this; } @@ -419,6 +547,7 @@ public final class DynamicMessage extends AbstractMessage { return this; } + @Override public Builder mergeUnknownFields(UnknownFieldSet unknownFields) { this.unknownFields = UnknownFieldSet.newBuilder(this.unknownFields) @@ -434,5 +563,41 @@ public final class DynamicMessage extends AbstractMessage { "FieldDescriptor does not match message type."); } } + + /** Verifies that the oneof is an oneof of this message. */ + private void verifyOneofContainingType(OneofDescriptor oneof) { + if (oneof.getContainingType() != type) { + throw new IllegalArgumentException( + "OneofDescriptor does not match message type."); + } + } + + /** Verifies that the value is EnumValueDescriptor and matchs Enum Type. */ + private void verifyEnumType(FieldDescriptor field, Object value) { + if (value == null) { + throw new NullPointerException(); + } + if (!(value instanceof EnumValueDescriptor)) { + throw new IllegalArgumentException( + "DynamicMessage should use EnumValueDescriptor to set Enum Value."); + } + if (field.getEnumType() != ((EnumValueDescriptor) value).getType()) { + throw new IllegalArgumentException( + "EnumValueDescriptor doesn't much Enum Field."); + } + } + + private void ensureIsMutable() { + if (fields.isImmutable()) { + fields = fields.clone(); + } + } + + @Override + public com.google.protobuf.Message.Builder getFieldBuilder(FieldDescriptor field) { + // TODO(xiangl): need implementation for dynamic message + throw new UnsupportedOperationException( + "getFieldBuilder() called on a dynamic message type."); + } } } diff --git a/java/src/main/java/com/google/protobuf/Extension.java b/java/src/main/java/com/google/protobuf/Extension.java new file mode 100644 index 0000000..4364e51 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/Extension.java @@ -0,0 +1,96 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +/** + * Interface that generated extensions implement. + * + * @author liujisi@google.com (Jisi Liu) + */ +public abstract class Extension { + /** Returns the field number of the extension. */ + public abstract int getNumber(); + + /** Returns the type of the field. */ + public abstract WireFormat.FieldType getLiteType(); + + /** Returns whether it is a repeated field. */ + public abstract boolean isRepeated(); + + /** Returns the descriptor of the extension. */ + public abstract Descriptors.FieldDescriptor getDescriptor(); + + /** Returns the default value of the extension field. */ + public abstract Type getDefaultValue(); + + /** + * Returns the default instance of the extension field, if it's a message + * extension. + */ + public abstract MessageLite getMessageDefaultInstance(); + + // All the methods below are extension implementation details. + + /** + * The API type that the extension is used for. + */ + protected enum ExtensionType { + IMMUTABLE, + MUTABLE, + PROTO1, + } + + protected ExtensionType getExtensionType() { + // TODO(liujisi): make this abstract after we fix proto1. + return ExtensionType.IMMUTABLE; + } + + /** + * Type of a message extension. + */ + public enum MessageType { + PROTO1, + PROTO2, + } + + /** + * If the extension is a message extension (i.e., getLiteType() == MESSAGE), + * returns the type of the message, otherwise undefined. + */ + public MessageType getMessageType() { + return MessageType.PROTO2; + } + + protected abstract Object fromReflectionType(Object value); + protected abstract Object singularFromReflectionType(Object value); + protected abstract Object toReflectionType(Object value); + protected abstract Object singularToReflectionType(Object value); +} diff --git a/java/src/main/java/com/google/protobuf/ExtensionRegistry.java b/java/src/main/java/com/google/protobuf/ExtensionRegistry.java index d4f6ba9..2dfef3c 100644 --- a/java/src/main/java/com/google/protobuf/ExtensionRegistry.java +++ b/java/src/main/java/com/google/protobuf/ExtensionRegistry.java @@ -33,9 +33,12 @@ package com.google.protobuf; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; /** * A table of known extensions, searchable by name or field number. When @@ -90,7 +93,7 @@ import java.util.Map; * * @author kenton@google.com Kenton Varda */ -public final class ExtensionRegistry extends ExtensionRegistryLite { +public class ExtensionRegistry extends ExtensionRegistryLite { /** Construct a new, empty instance. */ public static ExtensionRegistry newInstance() { return new ExtensionRegistry(); @@ -101,6 +104,7 @@ public final class ExtensionRegistry extends ExtensionRegistryLite { return EMPTY; } + /** Returns an unmodifiable view of the registry. */ @Override public ExtensionRegistry getUnmodifiable() { @@ -130,42 +134,127 @@ public final class ExtensionRegistry extends ExtensionRegistryLite { } /** - * Find an extension by fully-qualified field name, in the proto namespace. - * I.e. {@code result.descriptor.fullName()} will match {@code fullName} if - * a match is found. + * Deprecated. Use {@link #findImmutableExtensionByName(String)} instead. + */ + public ExtensionInfo findExtensionByName(final String fullName) { + return findImmutableExtensionByName(fullName); + } + + /** + * Find an extension for immutable APIs by fully-qualified field name, + * in the proto namespace. i.e. {@code result.descriptor.fullName()} will + * match {@code fullName} if a match is found. * * @return Information about the extension if found, or {@code null} * otherwise. */ - public ExtensionInfo findExtensionByName(final String fullName) { - return extensionsByName.get(fullName); + public ExtensionInfo findImmutableExtensionByName(final String fullName) { + return immutableExtensionsByName.get(fullName); + } + + /** + * Find an extension for mutable APIs by fully-qualified field name, + * in the proto namespace. i.e. {@code result.descriptor.fullName()} will + * match {@code fullName} if a match is found. + * + * @return Information about the extension if found, or {@code null} + * otherwise. + */ + public ExtensionInfo findMutableExtensionByName(final String fullName) { + return mutableExtensionsByName.get(fullName); } /** - * Find an extension by containing type and field number. + * Deprecated. Use {@link #findImmutableExtensionByNumber( + * Descriptors.Descriptor, int)} + */ + public ExtensionInfo findExtensionByNumber( + final Descriptor containingType, final int fieldNumber) { + return findImmutableExtensionByNumber(containingType, fieldNumber); + } + + /** + * Find an extension by containing type and field number for immutable APIs. * * @return Information about the extension if found, or {@code null} * otherwise. */ - public ExtensionInfo findExtensionByNumber(final Descriptor containingType, - final int fieldNumber) { - return extensionsByNumber.get( + public ExtensionInfo findImmutableExtensionByNumber( + final Descriptor containingType, final int fieldNumber) { + return immutableExtensionsByNumber.get( new DescriptorIntPair(containingType, fieldNumber)); } + /** + * Find an extension by containing type and field number for mutable APIs. + * + * @return Information about the extension if found, or {@code null} + * otherwise. + */ + public ExtensionInfo findMutableExtensionByNumber( + final Descriptor containingType, final int fieldNumber) { + return mutableExtensionsByNumber.get( + new DescriptorIntPair(containingType, fieldNumber)); + } + + /** + * Find all extensions for mutable APIs by fully-qualified name of + * extended class. Note that this method is more computationally expensive + * than getting a single extension by name or number. + * + * @return Information about the extensions found, or {@code null} if there + * are none. + */ + public Set getAllMutableExtensionsByExtendedType(final String fullName) { + HashSet extensions = new HashSet(); + for (DescriptorIntPair pair : mutableExtensionsByNumber.keySet()) { + if (pair.descriptor.getFullName().equals(fullName)) { + extensions.add(mutableExtensionsByNumber.get(pair)); + } + } + return extensions; + } + + /** + * Find all extensions for immutable APIs by fully-qualified name of + * extended class. Note that this method is more computationally expensive + * than getting a single extension by name or number. + * + * @return Information about the extensions found, or {@code null} if there + * are none. + */ + public Set getAllImmutableExtensionsByExtendedType(final String fullName) { + HashSet extensions = new HashSet(); + for (DescriptorIntPair pair : immutableExtensionsByNumber.keySet()) { + if (pair.descriptor.getFullName().equals(fullName)) { + extensions.add(immutableExtensionsByNumber.get(pair)); + } + } + return extensions; + } + /** Add an extension from a generated file to the registry. */ - public void add(final GeneratedMessage.GeneratedExtension extension) { + public void add(final Extension extension) { + if (extension.getExtensionType() != Extension.ExtensionType.IMMUTABLE && + extension.getExtensionType() != Extension.ExtensionType.MUTABLE) { + // do not support other extension types. ignore + return; + } + add(newExtensionInfo(extension), extension.getExtensionType()); + } + + static ExtensionInfo newExtensionInfo(final Extension extension) { if (extension.getDescriptor().getJavaType() == FieldDescriptor.JavaType.MESSAGE) { if (extension.getMessageDefaultInstance() == null) { throw new IllegalStateException( "Registered message-type extension had null default instance: " + - extension.getDescriptor().getFullName()); + extension.getDescriptor().getFullName()); } - add(new ExtensionInfo(extension.getDescriptor(), - extension.getMessageDefaultInstance())); + return new ExtensionInfo(extension.getDescriptor(), + (Message) extension.getMessageDefaultInstance()); } else { - add(new ExtensionInfo(extension.getDescriptor(), null)); + return new ExtensionInfo(extension.getDescriptor(), null); } } @@ -176,7 +265,9 @@ public final class ExtensionRegistry extends ExtensionRegistryLite { "ExtensionRegistry.add() must be provided a default instance when " + "adding an embedded message extension."); } - add(new ExtensionInfo(type, null)); + ExtensionInfo info = new ExtensionInfo(type, null); + add(info, Extension.ExtensionType.IMMUTABLE); + add(info, Extension.ExtensionType.MUTABLE); } /** Add a message-type extension to the registry by descriptor. */ @@ -186,40 +277,75 @@ public final class ExtensionRegistry extends ExtensionRegistryLite { "ExtensionRegistry.add() provided a default instance for a " + "non-message extension."); } - add(new ExtensionInfo(type, defaultInstance)); + add(new ExtensionInfo(type, defaultInstance), + Extension.ExtensionType.IMMUTABLE); } // ================================================================= // Private stuff. private ExtensionRegistry() { - this.extensionsByName = new HashMap(); - this.extensionsByNumber = new HashMap(); + this.immutableExtensionsByName = new HashMap(); + this.mutableExtensionsByName = new HashMap(); + this.immutableExtensionsByNumber = + new HashMap(); + this.mutableExtensionsByNumber = + new HashMap(); } private ExtensionRegistry(ExtensionRegistry other) { super(other); - this.extensionsByName = Collections.unmodifiableMap(other.extensionsByName); - this.extensionsByNumber = - Collections.unmodifiableMap(other.extensionsByNumber); + this.immutableExtensionsByName = + Collections.unmodifiableMap(other.immutableExtensionsByName); + this.mutableExtensionsByName = + Collections.unmodifiableMap(other.mutableExtensionsByName); + this.immutableExtensionsByNumber = + Collections.unmodifiableMap(other.immutableExtensionsByNumber); + this.mutableExtensionsByNumber = + Collections.unmodifiableMap(other.mutableExtensionsByNumber); } - private final Map extensionsByName; - private final Map extensionsByNumber; + private final Map immutableExtensionsByName; + private final Map mutableExtensionsByName; + private final Map immutableExtensionsByNumber; + private final Map mutableExtensionsByNumber; - private ExtensionRegistry(boolean empty) { + ExtensionRegistry(boolean empty) { super(ExtensionRegistryLite.getEmptyRegistry()); - this.extensionsByName = Collections.emptyMap(); - this.extensionsByNumber = + this.immutableExtensionsByName = + Collections.emptyMap(); + this.mutableExtensionsByName = + Collections.emptyMap(); + this.immutableExtensionsByNumber = Collections.emptyMap(); + this.mutableExtensionsByNumber = + Collections.emptyMap(); } private static final ExtensionRegistry EMPTY = new ExtensionRegistry(true); - private void add(final ExtensionInfo extension) { + private void add( + final ExtensionInfo extension, + final Extension.ExtensionType extensionType) { if (!extension.descriptor.isExtension()) { throw new IllegalArgumentException( - "ExtensionRegistry.add() was given a FieldDescriptor for a regular " + - "(non-extension) field."); + "ExtensionRegistry.add() was given a FieldDescriptor for a regular " + + "(non-extension) field."); + } + + Map extensionsByName; + Map extensionsByNumber; + switch (extensionType) { + case IMMUTABLE: + extensionsByName = immutableExtensionsByName; + extensionsByNumber = immutableExtensionsByNumber; + break; + case MUTABLE: + extensionsByName = mutableExtensionsByName; + extensionsByNumber = mutableExtensionsByNumber; + break; + default: + // Ignore the unknown supported type. + return; } extensionsByName.put(extension.descriptor.getFullName(), extension); diff --git a/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java index d5288dd..1e1289d 100644 --- a/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java +++ b/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java @@ -43,7 +43,7 @@ import java.util.Map; * make sense to mix the two, since if you have any regular types in your * program, you then require the full runtime and lose all the benefits of * the lite runtime, so you might as well make all your types be regular types. - * However, in some cases (e.g. when depending on multiple third-patry libraries + * However, in some cases (e.g. when depending on multiple third-party libraries * where one uses lite types and one uses regular), you may find yourself * wanting to mix the two. In this case things get more complicated. *

@@ -71,6 +71,22 @@ import java.util.Map; * @author kenton@google.com Kenton Varda */ public class ExtensionRegistryLite { + + // Set true to enable lazy parsing feature for MessageSet. + // + // TODO(xiangl): Now we use a global flag to control whether enable lazy + // parsing feature for MessageSet, which may be too crude for some + // applications. Need to support this feature on smaller granularity. + private static volatile boolean eagerlyParseMessageSets = false; + + public static boolean isEagerlyParseMessageSets() { + return eagerlyParseMessageSets; + } + + public static void setEagerlyParseMessageSets(boolean isEagerlyParse) { + eagerlyParseMessageSets = isEagerlyParse; + } + /** Construct a new, empty instance. */ public static ExtensionRegistryLite newInstance() { return new ExtensionRegistryLite(); diff --git a/java/src/main/java/com/google/protobuf/FieldSet.java b/java/src/main/java/com/google/protobuf/FieldSet.java index 93e55f2..01b6a35 100644 --- a/java/src/main/java/com/google/protobuf/FieldSet.java +++ b/java/src/main/java/com/google/protobuf/FieldSet.java @@ -30,13 +30,14 @@ package com.google.protobuf; +import com.google.protobuf.LazyField.LazyIterator; + +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; -import java.util.TreeMap; import java.util.List; import java.util.Map; -import java.io.IOException; /** * A class which represents an arbitrary set of fields of some message type. @@ -67,16 +68,13 @@ final class FieldSet fields; + private final SmallSortedMap fields; + private boolean isImmutable; + private boolean hasLazyField = false; /** Construct a new FieldSet. */ private FieldSet() { - // Use a TreeMap because fields need to be in canonical order when - // serializing. - // TODO(kenton): Maybe use some sort of sparse array instead? It would - // even make sense to store the first 16 or so tags in a flat array - // to make DynamicMessage faster. - fields = new TreeMap(); + this.fields = SmallSortedMap.newFieldMap(16); } /** @@ -84,7 +82,8 @@ final class FieldSet emptySet() { return DEFAULT_INSTANCE; } - @SuppressWarnings("unchecked") + @SuppressWarnings("rawtypes") private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true); /** Make this FieldSet immutable from this point forward. */ @SuppressWarnings("unchecked") public void makeImmutable() { - for (final Map.Entry entry: - fields.entrySet()) { - if (entry.getKey().isRepeated()) { - final List value = (List)entry.getValue(); - fields.put(entry.getKey(), Collections.unmodifiableList(value)); - } + if (isImmutable) { + return; + } + fields.makeImmutable(); + isImmutable = true; + } + + /** + * Returns whether the FieldSet is immutable. This is true if it is the + * {@link #emptySet} or if {@link #makeImmutable} were called. + * + * @return whether the FieldSet is immutable. + */ + public boolean isImmutable() { + return isImmutable; + } + + /** + * Clones the FieldSet. The returned FieldSet will be mutable even if the + * original FieldSet was immutable. + * + * @return the newly cloned FieldSet + */ + @Override + public FieldSet clone() { + // We can't just call fields.clone because List objects in the map + // should not be shared. + FieldSet clone = FieldSet.newFieldSet(); + for (int i = 0; i < fields.getNumArrayEntries(); i++) { + Map.Entry entry = fields.getArrayEntryAt(i); + FieldDescriptorType descriptor = entry.getKey(); + clone.setField(descriptor, entry.getValue()); + } + for (Map.Entry entry : + fields.getOverflowEntries()) { + FieldDescriptorType descriptor = entry.getKey(); + clone.setField(descriptor, entry.getValue()); } - fields = Collections.unmodifiableMap(fields); + clone.hasLazyField = hasLazyField; + return clone; } + // ================================================================= /** See {@link Message.Builder#clear()}. */ public void clear() { fields.clear(); + hasLazyField = false; } /** * Get a simple map containing all the fields. */ public Map getAllFields() { - return Collections.unmodifiableMap(fields); + if (hasLazyField) { + SmallSortedMap result = + SmallSortedMap.newFieldMap(16); + for (int i = 0; i < fields.getNumArrayEntries(); i++) { + cloneFieldEntry(result, fields.getArrayEntryAt(i)); + } + for (Map.Entry entry : + fields.getOverflowEntries()) { + cloneFieldEntry(result, entry); + } + if (fields.isImmutable()) { + result.makeImmutable(); + } + return result; + } + return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields); + } + + private void cloneFieldEntry(Map map, + Map.Entry entry) { + FieldDescriptorType key = entry.getKey(); + Object value = entry.getValue(); + if (value instanceof LazyField) { + map.put(key, ((LazyField) value).getValue()); + } else { + map.put(key, value); + } } /** - * Get an iterator to the field map. This iterator should not be leaked - * out of the protobuf library as it is not protected from mutation. + * Get an iterator to the field map. This iterator should not be leaked out + * of the protobuf library as it is not protected from mutation when fields + * is not immutable. */ public Iterator> iterator() { + if (hasLazyField) { + return new LazyIterator( + fields.entrySet().iterator()); + } return fields.entrySet().iterator(); } @@ -157,14 +221,18 @@ final class FieldSet) value).size(); } } @@ -225,12 +299,12 @@ final class FieldSet) value).get(index); } } @@ -247,13 +321,13 @@ final class FieldSet) list).set(index, value); } /** @@ -270,13 +344,13 @@ final class FieldSet list; if (existingValue == null) { - list = new ArrayList(); + list = new ArrayList(); fields.put(descriptor, list); } else { - list = (List) existingValue; + list = (List) existingValue; } list.add(value); @@ -303,14 +377,18 @@ final class FieldSet entry: - fields.entrySet()) { - final FieldDescriptorType descriptor = entry.getKey(); - if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { - if (descriptor.isRepeated()) { - for (final MessageLite element: - (List) entry.getValue()) { - if (!element.isInitialized()) { - return false; - } + for (int i = 0; i < fields.getNumArrayEntries(); i++) { + if (!isInitialized(fields.getArrayEntryAt(i))) { + return false; + } + } + for (final Map.Entry entry : + fields.getOverflowEntries()) { + if (!isInitialized(entry)) { + return false; + } + } + return true; + } + + @SuppressWarnings("unchecked") + private boolean isInitialized( + final Map.Entry entry) { + final FieldDescriptorType descriptor = entry.getKey(); + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { + if (descriptor.isRepeated()) { + for (final MessageLite element: + (List) entry.getValue()) { + if (!element.isInitialized()) { + return false; } - } else { - if (!((MessageLite) entry.getValue()).isInitialized()) { + } + } else { + Object value = entry.getValue(); + if (value instanceof MessageLite) { + if (!((MessageLite) value).isInitialized()) { return false; } + } else if (value instanceof LazyField) { + return true; + } else { + throw new IllegalArgumentException( + "Wrong object type used with protocol message reflection."); } } } - return true; } @@ -376,41 +474,62 @@ final class FieldSet other) { - for (final Map.Entry entry: - other.fields.entrySet()) { - final FieldDescriptorType descriptor = entry.getKey(); - final Object otherValue = entry.getValue(); + for (int i = 0; i < other.fields.getNumArrayEntries(); i++) { + mergeFromField(other.fields.getArrayEntryAt(i)); + } + for (final Map.Entry entry : + other.fields.getOverflowEntries()) { + mergeFromField(entry); + } + } - if (descriptor.isRepeated()) { - Object value = fields.get(descriptor); - if (value == null) { - // Our list is empty, but we still need to make a defensive copy of - // the other list since we don't know if the other FieldSet is still - // mutable. - fields.put(descriptor, new ArrayList((List) otherValue)); - } else { - // Concatenate the lists. - ((List) value).addAll((List) otherValue); - } - } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { - Object value = fields.get(descriptor); - if (value == null) { - fields.put(descriptor, otherValue); - } else { - // Merge the messages. - fields.put(descriptor, - descriptor.internalMergeFrom( - ((MessageLite) value).toBuilder(), (MessageLite) otherValue) - .build()); - } + private Object cloneIfMutable(Object value) { + if (value instanceof byte[]) { + byte[] bytes = (byte[]) value; + byte[] copy = new byte[bytes.length]; + System.arraycopy(bytes, 0, copy, 0, bytes.length); + return copy; + } else { + return value; + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private void mergeFromField( + final Map.Entry entry) { + final FieldDescriptorType descriptor = entry.getKey(); + Object otherValue = entry.getValue(); + if (otherValue instanceof LazyField) { + otherValue = ((LazyField) otherValue).getValue(); + } + if (descriptor.isRepeated()) { + Object value = getField(descriptor); + if (value == null) { + value = new ArrayList(); + } + for (Object element : (List) otherValue) { + ((List) value).add(cloneIfMutable(element)); + } + fields.put(descriptor, value); + } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { + Object value = getField(descriptor); + if (value == null) { + fields.put(descriptor, cloneIfMutable(otherValue)); } else { - fields.put(descriptor, otherValue); + // Merge the messages. + value = descriptor.internalMergeFrom( + ((MessageLite) value).toBuilder(), (MessageLite) otherValue) + .build(); + + fields.put(descriptor, value); } + } else { + fields.put(descriptor, cloneIfMutable(otherValue)); } } @@ -418,11 +537,13 @@ final class FieldSet entry: - fields.entrySet()) { + for (int i = 0; i < fields.getNumArrayEntries(); i++) { + final Map.Entry entry = + fields.getArrayEntryAt(i); + writeField(entry.getKey(), entry.getValue(), output); + } + for (final Map.Entry entry : + fields.getOverflowEntries()) { writeField(entry.getKey(), entry.getValue(), output); } } @@ -479,16 +611,29 @@ final class FieldSet entry: - fields.entrySet()) { - final FieldDescriptorType descriptor = entry.getKey(); - if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE && - !descriptor.isRepeated() && !descriptor.isPacked()) { - output.writeMessageSetExtension(entry.getKey().getNumber(), - (MessageLite) entry.getValue()); - } else { - writeField(descriptor, entry.getValue(), output); + for (int i = 0; i < fields.getNumArrayEntries(); i++) { + writeMessageSetTo(fields.getArrayEntryAt(i), output); + } + for (final Map.Entry entry : + fields.getOverflowEntries()) { + writeMessageSetTo(entry, output); + } + } + + private void writeMessageSetTo( + final Map.Entry entry, + final CodedOutputStream output) throws IOException { + final FieldDescriptorType descriptor = entry.getKey(); + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE && + !descriptor.isRepeated() && !descriptor.isPacked()) { + Object value = entry.getValue(); + if (value instanceof LazyField) { + value = ((LazyField) value).getValue(); } + output.writeMessageSetExtension(entry.getKey().getNumber(), + (MessageLite) value); + } else { + writeField(descriptor, entry.getValue(), output); } } @@ -510,7 +655,7 @@ final class FieldSet valueList = (List)value; if (descriptor.isPacked()) { output.writeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED); // Compute the total data size so the length can be written. @@ -583,7 +738,11 @@ final class FieldSet entry: - fields.entrySet()) { + for (int i = 0; i < fields.getNumArrayEntries(); i++) { + final Map.Entry entry = + fields.getArrayEntryAt(i); + size += computeFieldSize(entry.getKey(), entry.getValue()); + } + for (final Map.Entry entry : + fields.getOverflowEntries()) { size += computeFieldSize(entry.getKey(), entry.getValue()); } return size; @@ -605,18 +769,32 @@ final class FieldSet entry: - fields.entrySet()) { - final FieldDescriptorType descriptor = entry.getKey(); - if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE && - !descriptor.isRepeated() && !descriptor.isPacked()) { - size += CodedOutputStream.computeMessageSetExtensionSize( - entry.getKey().getNumber(), (MessageLite) entry.getValue()); + for (int i = 0; i < fields.getNumArrayEntries(); i++) { + size += getMessageSetSerializedSize(fields.getArrayEntryAt(i)); + } + for (final Map.Entry entry : + fields.getOverflowEntries()) { + size += getMessageSetSerializedSize(entry); + } + return size; + } + + private int getMessageSetSerializedSize( + final Map.Entry entry) { + final FieldDescriptorType descriptor = entry.getKey(); + Object value = entry.getValue(); + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE + && !descriptor.isRepeated() && !descriptor.isPacked()) { + if (value instanceof LazyField) { + return CodedOutputStream.computeLazyFieldMessageSetExtensionSize( + entry.getKey().getNumber(), (LazyField) value); } else { - size += computeFieldSize(descriptor, entry.getValue()); + return CodedOutputStream.computeMessageSetExtensionSize( + entry.getKey().getNumber(), (MessageLite) value); } + } else { + return computeFieldSize(descriptor, value); } - return size; } /** @@ -635,7 +813,9 @@ final class FieldSet)value) { dataSize += computeElementSizeNoTag(type, element); } return dataSize + @@ -700,7 +895,7 @@ final class FieldSet)value) { size += computeElementSize(type, number, element); } return size; diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java index dba0ec8..b7cf269 100644 --- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java +++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java @@ -33,10 +33,14 @@ package com.google.protobuf; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.FileDescriptor; +import com.google.protobuf.Descriptors.OneofDescriptor; import java.io.IOException; -import java.lang.reflect.Method; +import java.io.ObjectStreamException; +import java.io.Serializable; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -52,10 +56,37 @@ import java.util.TreeMap; * * @author kenton@google.com Kenton Varda */ -public abstract class GeneratedMessage extends AbstractMessage { - protected GeneratedMessage() {} +public abstract class GeneratedMessage extends AbstractMessage + implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * For testing. Allows a test to disable the optimization that avoids using + * field builders for nested messages until they are requested. By disabling + * this optimization, existing tests can be reused to test the field builders. + */ + protected static boolean alwaysUseFieldBuilders = false; + + protected GeneratedMessage() { + } - private UnknownFieldSet unknownFields = UnknownFieldSet.getDefaultInstance(); + protected GeneratedMessage(Builder builder) { + } + + public Parser getParserForType() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + + /** + * For testing. Allows a test to disable the optimization that avoids using + * field builders for nested messages until they are requested. By disabling + * this optimization, existing tests can be reused to test the field builders. + * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}. + */ + static void enableAlwaysUseFieldBuildersForTesting() { + alwaysUseFieldBuilders = true; + } /** * Get the FieldAccessorTable for this type. We can't have the message @@ -64,6 +95,7 @@ public abstract class GeneratedMessage extends AbstractMessage { */ protected abstract FieldAccessorTable internalGetFieldAccessorTable(); + //@Override (Java 1.6 override semantics, but we must support 1.5) public Descriptor getDescriptorForType() { return internalGetFieldAccessorTable().descriptor; } @@ -75,7 +107,7 @@ public abstract class GeneratedMessage extends AbstractMessage { final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; for (final FieldDescriptor field : descriptor.getFields()) { if (field.isRepeated()) { - final List value = (List) getField(field); + final List value = (List) getField(field); if (!value.isEmpty()) { result.put(field, value); } @@ -118,36 +150,146 @@ public abstract class GeneratedMessage extends AbstractMessage { return true; } + //@Override (Java 1.6 override semantics, but we must support 1.5) public Map getAllFields() { return Collections.unmodifiableMap(getAllFieldsMutable()); } + //@Override (Java 1.6 override semantics, but we must support 1.5) + public boolean hasOneof(final OneofDescriptor oneof) { + return internalGetFieldAccessorTable().getOneof(oneof).has(this); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) { + return internalGetFieldAccessorTable().getOneof(oneof).get(this); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) public boolean hasField(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field).has(this); } + //@Override (Java 1.6 override semantics, but we must support 1.5) public Object getField(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field).get(this); } + //@Override (Java 1.6 override semantics, but we must support 1.5) public int getRepeatedFieldCount(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field) .getRepeatedCount(this); } + //@Override (Java 1.6 override semantics, but we must support 1.5) public Object getRepeatedField(final FieldDescriptor field, final int index) { return internalGetFieldAccessorTable().getField(field) .getRepeated(this, index); } - public final UnknownFieldSet getUnknownFields() { - return unknownFields; + //@Override (Java 1.6 override semantics, but we must support 1.5) + public UnknownFieldSet getUnknownFields() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + + /** + * Called by subclasses to parse an unknown field. + * @return {@code true} unless the tag is an end-group tag. + */ + protected boolean parseUnknownField( + CodedInputStream input, + UnknownFieldSet.Builder unknownFields, + ExtensionRegistryLite extensionRegistry, + int tag) throws IOException { + return unknownFields.mergeFieldFrom(tag, input); + } + + + /** + * Used by parsing constructors in generated classes. + */ + protected void makeExtensionsImmutable() { + // Noop for messages without extensions. + } + + protected abstract Message.Builder newBuilderForType(BuilderParent parent); + + /** + * Interface for the parent of a Builder that allows the builder to + * communicate invalidations back to the parent for use when using nested + * builders. + */ + protected interface BuilderParent { + + /** + * A builder becomes dirty whenever a field is modified -- including fields + * in nested builders -- and becomes clean when build() is called. Thus, + * when a builder becomes dirty, all its parents become dirty as well, and + * when it becomes clean, all its children become clean. The dirtiness + * state is used to invalidate certain cached values. + *
+ * To this end, a builder calls markAsDirty() on its parent whenever it + * transitions from clean to dirty. The parent must propagate this call to + * its own parent, unless it was already dirty, in which case the + * grandparent must necessarily already be dirty as well. The parent can + * only transition back to "clean" after calling build() on all children. + */ + void markDirty(); } @SuppressWarnings("unchecked") public abstract static class Builder extends AbstractMessage.Builder { - protected Builder() {} + + private BuilderParent builderParent; + + private BuilderParentImpl meAsParent; + + // Indicates that we've built a message and so we are now obligated + // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener. + private boolean isClean; + + private UnknownFieldSet unknownFields = + UnknownFieldSet.getDefaultInstance(); + + protected Builder() { + this(null); + } + + protected Builder(BuilderParent builderParent) { + this.builderParent = builderParent; + } + + void dispose() { + builderParent = null; + } + + /** + * Called by the subclass when a message is built. + */ + protected void onBuilt() { + if (builderParent != null) { + markClean(); + } + } + + /** + * Called by the subclass or a builder to notify us that a message was + * built and may be cached and therefore invalidations are needed. + */ + protected void markClean() { + this.isClean = true; + } + + /** + * Gets whether invalidations are needed + * + * @return whether invalidations are needed + */ + protected boolean isClean() { + return isClean; + } // This is implemented here only to work around an apparent bug in the // Java compiler and/or build system. See bug #1898463. The mere presence @@ -159,26 +301,50 @@ public abstract class GeneratedMessage extends AbstractMessage { } /** - * Get the message being built. We don't just pass this to the - * constructor because it becomes null when build() is called. + * Called by the initialization and clear code paths to allow subclasses to + * reset any of their builtin fields back to the initial values. */ - protected abstract GeneratedMessage internalGetResult(); + public BuilderType clear() { + unknownFields = UnknownFieldSet.getDefaultInstance(); + onChanged(); + return (BuilderType) this; + } /** * Get the FieldAccessorTable for this type. We can't have the message * class pass this in to the constructor because of bootstrapping trouble * with DescriptorProtos. */ - private FieldAccessorTable internalGetFieldAccessorTable() { - return internalGetResult().internalGetFieldAccessorTable(); - } + protected abstract FieldAccessorTable internalGetFieldAccessorTable(); + //@Override (Java 1.6 override semantics, but we must support 1.5) public Descriptor getDescriptorForType() { return internalGetFieldAccessorTable().descriptor; } + //@Override (Java 1.6 override semantics, but we must support 1.5) public Map getAllFields() { - return internalGetResult().getAllFields(); + return Collections.unmodifiableMap(getAllFieldsMutable()); + } + + /** Internal helper which returns a mutable map. */ + private Map getAllFieldsMutable() { + final TreeMap result = + new TreeMap(); + final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; + for (final FieldDescriptor field : descriptor.getFields()) { + if (field.isRepeated()) { + final List value = (List) getField(field); + if (!value.isEmpty()) { + result.put(field, value); + } + } else { + if (hasField(field)) { + result.put(field, getField(field)); + } + } + } + return result; } public Message.Builder newBuilderForField( @@ -186,18 +352,35 @@ public abstract class GeneratedMessage extends AbstractMessage { return internalGetFieldAccessorTable().getField(field).newBuilder(); } + //@Override (Java 1.6 override semantics, but we must support 1.5) + public Message.Builder getFieldBuilder(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field).getBuilder(this); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public boolean hasOneof(final OneofDescriptor oneof) { + return internalGetFieldAccessorTable().getOneof(oneof).has(this); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) { + return internalGetFieldAccessorTable().getOneof(oneof).get(this); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) public boolean hasField(final FieldDescriptor field) { - return internalGetResult().hasField(field); + return internalGetFieldAccessorTable().getField(field).has(this); } + //@Override (Java 1.6 override semantics, but we must support 1.5) public Object getField(final FieldDescriptor field) { + Object object = internalGetFieldAccessorTable().getField(field).get(this); if (field.isRepeated()) { // The underlying list object is still modifiable at this point. // Make sure not to expose the modifiable list to the caller. - return Collections.unmodifiableList( - (List) internalGetResult().getField(field)); + return Collections.unmodifiableList((List) object); } else { - return internalGetResult().getField(field); + return object; } } @@ -207,18 +390,29 @@ public abstract class GeneratedMessage extends AbstractMessage { return (BuilderType) this; } + //@Override (Java 1.6 override semantics, but we must support 1.5) public BuilderType clearField(final FieldDescriptor field) { internalGetFieldAccessorTable().getField(field).clear(this); return (BuilderType) this; } + //@Override (Java 1.6 override semantics, but we must support 1.5) + public BuilderType clearOneof(final OneofDescriptor oneof) { + internalGetFieldAccessorTable().getOneof(oneof).clear(this); + return (BuilderType) this; + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) public int getRepeatedFieldCount(final FieldDescriptor field) { - return internalGetResult().getRepeatedFieldCount(field); + return internalGetFieldAccessorTable().getField(field) + .getRepeatedCount(this); } + //@Override (Java 1.6 override semantics, but we must support 1.5) public Object getRepeatedField(final FieldDescriptor field, final int index) { - return internalGetResult().getRepeatedField(field, index); + return internalGetFieldAccessorTable().getField(field) + .getRepeated(this, index); } public BuilderType setRepeatedField(final FieldDescriptor field, @@ -234,29 +428,57 @@ public abstract class GeneratedMessage extends AbstractMessage { return (BuilderType) this; } - public final UnknownFieldSet getUnknownFields() { - return internalGetResult().unknownFields; - } - public final BuilderType setUnknownFields( final UnknownFieldSet unknownFields) { - internalGetResult().unknownFields = unknownFields; + this.unknownFields = unknownFields; + onChanged(); return (BuilderType) this; } @Override public final BuilderType mergeUnknownFields( final UnknownFieldSet unknownFields) { - final GeneratedMessage result = internalGetResult(); - result.unknownFields = - UnknownFieldSet.newBuilder(result.unknownFields) + this.unknownFields = + UnknownFieldSet.newBuilder(this.unknownFields) .mergeFrom(unknownFields) .build(); + onChanged(); return (BuilderType) this; } + //@Override (Java 1.6 override semantics, but we must support 1.5) public boolean isInitialized() { - return internalGetResult().isInitialized(); + for (final FieldDescriptor field : getDescriptorForType().getFields()) { + // Check that all required fields are present. + if (field.isRequired()) { + if (!hasField(field)) { + return false; + } + } + // Check that embedded messages are initialized. + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + @SuppressWarnings("unchecked") final + List messageList = (List) getField(field); + for (final Message element : messageList) { + if (!element.isInitialized()) { + return false; + } + } + } else { + if (hasField(field) && + !((Message) getField(field)).isInitialized()) { + return false; + } + } + } + } + return true; + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public final UnknownFieldSet getUnknownFields() { + return unknownFields; } /** @@ -270,11 +492,71 @@ public abstract class GeneratedMessage extends AbstractMessage { final int tag) throws IOException { return unknownFields.mergeFieldFrom(tag, input); } + + /** + * Implementation of {@link BuilderParent} for giving to our children. This + * small inner class makes it so we don't publicly expose the BuilderParent + * methods. + */ + private class BuilderParentImpl implements BuilderParent { + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void markDirty() { + onChanged(); + } + } + + /** + * Gets the {@link BuilderParent} for giving to our children. + * @return The builder parent for our children. + */ + protected BuilderParent getParentForChildren() { + if (meAsParent == null) { + meAsParent = new BuilderParentImpl(); + } + return meAsParent; + } + + /** + * Called when a the builder or one of its nested children has changed + * and any parent should be notified of its invalidation. + */ + protected final void onChanged() { + if (isClean && builderParent != null) { + builderParent.markDirty(); + + // Don't keep dispatching invalidations until build is called again. + isClean = false; + } + } } // ================================================================= // Extensions-related stuff + public interface ExtendableMessageOrBuilder< + MessageType extends ExtendableMessage> extends MessageOrBuilder { + // Re-define for return type covariance. + Message getDefaultInstanceForType(); + + /** Check if a singular extension is present. */ + boolean hasExtension( + Extension extension); + + /** Get the number of elements in a repeated extension. */ + int getExtensionCount( + Extension> extension); + + /** Get the value of an extension. */ + Type getExtension( + Extension extension); + + /** Get one element of a repeated extension. */ + Type getExtension( + Extension> extension, + int index); + } + /** * Generated message classes for message types that contain extension ranges * subclass this. @@ -312,12 +594,23 @@ public abstract class GeneratedMessage extends AbstractMessage { */ public abstract static class ExtendableMessage< MessageType extends ExtendableMessage> - extends GeneratedMessage { - protected ExtendableMessage() {} - private final FieldSet extensions = FieldSet.newFieldSet(); + extends GeneratedMessage + implements ExtendableMessageOrBuilder { + + private final FieldSet extensions; + + protected ExtendableMessage() { + this.extensions = FieldSet.newFieldSet(); + } + + protected ExtendableMessage( + ExtendableBuilder builder) { + super(builder); + this.extensions = builder.buildExtensions(); + } private void verifyExtensionContainingType( - final GeneratedExtension extension) { + final Extension extension) { if (extension.getDescriptor().getContainingType() != getDescriptorForType()) { // This can only happen if someone uses unchecked operations. @@ -330,24 +623,27 @@ public abstract class GeneratedMessage extends AbstractMessage { } /** Check if a singular extension is present. */ - public final boolean hasExtension( - final GeneratedExtension extension) { + //@Override (Java 1.6 override semantics, but we must support 1.5) + public final boolean hasExtension( + final Extension extension) { verifyExtensionContainingType(extension); return extensions.hasField(extension.getDescriptor()); } /** Get the number of elements in a repeated extension. */ + //@Override (Java 1.6 override semantics, but we must support 1.5) public final int getExtensionCount( - final GeneratedExtension> extension) { + final Extension> extension) { verifyExtensionContainingType(extension); final FieldDescriptor descriptor = extension.getDescriptor(); return extensions.getRepeatedFieldCount(descriptor); } /** Get the value of an extension. */ + //@Override (Java 1.6 override semantics, but we must support 1.5) @SuppressWarnings("unchecked") public final Type getExtension( - final GeneratedExtension extension) { + final Extension extension) { verifyExtensionContainingType(extension); FieldDescriptor descriptor = extension.getDescriptor(); final Object value = extensions.getField(descriptor); @@ -367,9 +663,10 @@ public abstract class GeneratedMessage extends AbstractMessage { } /** Get one element of a repeated extension. */ + //@Override (Java 1.6 override semantics, but we must support 1.5) @SuppressWarnings("unchecked") public final Type getExtension( - final GeneratedExtension> extension, + final Extension> extension, final int index) { verifyExtensionContainingType(extension); FieldDescriptor descriptor = extension.getDescriptor(); @@ -387,6 +684,26 @@ public abstract class GeneratedMessage extends AbstractMessage { return super.isInitialized() && extensionsAreInitialized(); } + @Override + protected boolean parseUnknownField( + CodedInputStream input, + UnknownFieldSet.Builder unknownFields, + ExtensionRegistryLite extensionRegistry, + int tag) throws IOException { + return MessageReflection.mergeFieldFrom( + input, unknownFields, extensionRegistry, getDescriptorForType(), + new MessageReflection.ExtensionAdapter(extensions), tag); + } + + + /** + * Used by parsing constructors in generated classes. + */ + @Override + protected void makeExtensionsImmutable() { + extensions.makeImmutable(); + } + /** * Used by subclasses to serialize extensions. Extension ranges may be * interleaved with field numbers, but we must write them in canonical @@ -416,9 +733,21 @@ public abstract class GeneratedMessage extends AbstractMessage { if (messageSetWireFormat && descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE && !descriptor.isRepeated()) { - output.writeMessageSetExtension(descriptor.getNumber(), - (Message) next.getValue()); + if (next instanceof LazyField.LazyEntry) { + output.writeRawMessageSetExtension(descriptor.getNumber(), + ((LazyField.LazyEntry) next).getField().toByteString()); + } else { + output.writeMessageSetExtension(descriptor.getNumber(), + (Message) next.getValue()); + } } else { + // TODO(xiangl): Taken care of following code, it may cause + // problem when we use LazyField for normal fields/extensions. + // Due to the optional field can be duplicated at the end of + // serialized bytes, which will make the serialized size change + // after lazy field parsed. So when we use LazyField globally, + // we need to change the following write method to write cached + // bytes directly rather than write the parsed message. FieldSet.writeField(descriptor, next.getValue(), output); } if (iter.hasNext()) { @@ -448,10 +777,14 @@ public abstract class GeneratedMessage extends AbstractMessage { // --------------------------------------------------------------- // Reflection + protected Map getExtensionFields() { + return extensions.getAllFields(); + } + @Override public Map getAllFields() { final Map result = super.getAllFieldsMutable(); - result.putAll(extensions.getAllFields()); + result.putAll(getExtensionFields()); return Collections.unmodifiableMap(result); } @@ -556,9 +889,29 @@ public abstract class GeneratedMessage extends AbstractMessage { public abstract static class ExtendableBuilder< MessageType extends ExtendableMessage, BuilderType extends ExtendableBuilder> - extends Builder { + extends Builder + implements ExtendableMessageOrBuilder { + + private FieldSet extensions = FieldSet.emptySet(); + protected ExtendableBuilder() {} + protected ExtendableBuilder( + BuilderParent parent) { + super(parent); + } + + // For immutable message conversion. + void internalSetExtensionSet(FieldSet extensions) { + this.extensions = extensions; + } + + @Override + public BuilderType clear() { + extensions = FieldSet.emptySet(); + return super.clear(); + } + // This is implemented here only to work around an apparent bug in the // Java compiler and/or build system. See bug #1898463. The mere presence // of this dummy clone() implementation makes it go away. @@ -568,80 +921,143 @@ public abstract class GeneratedMessage extends AbstractMessage { "This is supposed to be overridden by subclasses."); } - @Override - protected abstract ExtendableMessage internalGetResult(); + private void ensureExtensionsIsMutable() { + if (extensions.isImmutable()) { + extensions = extensions.clone(); + } + } + + private void verifyExtensionContainingType( + final Extension extension) { + if (extension.getDescriptor().getContainingType() != + getDescriptorForType()) { + // This can only happen if someone uses unchecked operations. + throw new IllegalArgumentException( + "Extension is for type \"" + + extension.getDescriptor().getContainingType().getFullName() + + "\" which does not match message type \"" + + getDescriptorForType().getFullName() + "\"."); + } + } /** Check if a singular extension is present. */ - public final boolean hasExtension( - final GeneratedExtension extension) { - return internalGetResult().hasExtension(extension); + //@Override (Java 1.6 override semantics, but we must support 1.5) + public final boolean hasExtension( + final Extension extension) { + verifyExtensionContainingType(extension); + return extensions.hasField(extension.getDescriptor()); } /** Get the number of elements in a repeated extension. */ + //@Override (Java 1.6 override semantics, but we must support 1.5) public final int getExtensionCount( - final GeneratedExtension> extension) { - return internalGetResult().getExtensionCount(extension); + final Extension> extension) { + verifyExtensionContainingType(extension); + final FieldDescriptor descriptor = extension.getDescriptor(); + return extensions.getRepeatedFieldCount(descriptor); } /** Get the value of an extension. */ + //@Override (Java 1.6 override semantics, but we must support 1.5) public final Type getExtension( - final GeneratedExtension extension) { - return internalGetResult().getExtension(extension); + final Extension extension) { + verifyExtensionContainingType(extension); + FieldDescriptor descriptor = extension.getDescriptor(); + final Object value = extensions.getField(descriptor); + if (value == null) { + if (descriptor.isRepeated()) { + return (Type) Collections.emptyList(); + } else if (descriptor.getJavaType() == + FieldDescriptor.JavaType.MESSAGE) { + return (Type) extension.getMessageDefaultInstance(); + } else { + return (Type) extension.fromReflectionType( + descriptor.getDefaultValue()); + } + } else { + return (Type) extension.fromReflectionType(value); + } } /** Get one element of a repeated extension. */ + //@Override (Java 1.6 override semantics, but we must support 1.5) public final Type getExtension( - final GeneratedExtension> extension, + final Extension> extension, final int index) { - return internalGetResult().getExtension(extension, index); + verifyExtensionContainingType(extension); + FieldDescriptor descriptor = extension.getDescriptor(); + return (Type) extension.singularFromReflectionType( + extensions.getRepeatedField(descriptor, index)); } /** Set the value of an extension. */ public final BuilderType setExtension( - final GeneratedExtension extension, + final Extension extension, final Type value) { - final ExtendableMessage message = internalGetResult(); - message.verifyExtensionContainingType(extension); + verifyExtensionContainingType(extension); + ensureExtensionsIsMutable(); final FieldDescriptor descriptor = extension.getDescriptor(); - message.extensions.setField(descriptor, - extension.toReflectionType(value)); + extensions.setField(descriptor, extension.toReflectionType(value)); + onChanged(); return (BuilderType) this; } /** Set the value of one element of a repeated extension. */ public final BuilderType setExtension( - final GeneratedExtension> extension, + final Extension> extension, final int index, final Type value) { - final ExtendableMessage message = internalGetResult(); - message.verifyExtensionContainingType(extension); + verifyExtensionContainingType(extension); + ensureExtensionsIsMutable(); final FieldDescriptor descriptor = extension.getDescriptor(); - message.extensions.setRepeatedField( + extensions.setRepeatedField( descriptor, index, extension.singularToReflectionType(value)); + onChanged(); return (BuilderType) this; } /** Append a value to a repeated extension. */ public final BuilderType addExtension( - final GeneratedExtension> extension, + final Extension> extension, final Type value) { - final ExtendableMessage message = internalGetResult(); - message.verifyExtensionContainingType(extension); + verifyExtensionContainingType(extension); + ensureExtensionsIsMutable(); final FieldDescriptor descriptor = extension.getDescriptor(); - message.extensions.addRepeatedField( + extensions.addRepeatedField( descriptor, extension.singularToReflectionType(value)); + onChanged(); return (BuilderType) this; } /** Clear an extension. */ public final BuilderType clearExtension( - final GeneratedExtension extension) { - final ExtendableMessage message = internalGetResult(); - message.verifyExtensionContainingType(extension); - message.extensions.clearField(extension.getDescriptor()); + final Extension extension) { + verifyExtensionContainingType(extension); + ensureExtensionsIsMutable(); + extensions.clearField(extension.getDescriptor()); + onChanged(); return (BuilderType) this; } + /** Called by subclasses to check if all extensions are initialized. */ + protected boolean extensionsAreInitialized() { + return extensions.isInitialized(); + } + + /** + * Called by the build code path to create a copy of the extensions for + * building the message. + */ + private FieldSet buildExtensions() { + extensions.makeImmutable(); + return extensions; + } + + @Override + public boolean isInitialized() { + return super.isInitialized() && extensionsAreInitialized(); + } + /** * Called by subclasses to parse an unknown field or an extension. * @return {@code true} unless the tag is an end-group tag. @@ -652,24 +1068,81 @@ public abstract class GeneratedMessage extends AbstractMessage { final UnknownFieldSet.Builder unknownFields, final ExtensionRegistryLite extensionRegistry, final int tag) throws IOException { - final ExtendableMessage message = internalGetResult(); - return AbstractMessage.Builder.mergeFieldFrom( - input, unknownFields, extensionRegistry, this, tag); + return MessageReflection.mergeFieldFrom( + input, unknownFields, extensionRegistry, getDescriptorForType(), + new MessageReflection.BuilderAdapter(this), tag); } // --------------------------------------------------------------- // Reflection - // We don't have to override the get*() methods here because they already - // just forward to the underlying message. + @Override + public Map getAllFields() { + final Map result = super.getAllFieldsMutable(); + result.putAll(extensions.getAllFields()); + return Collections.unmodifiableMap(result); + } + + @Override + public Object getField(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + final Object value = extensions.getField(field); + if (value == null) { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + // Lacking an ExtensionRegistry, we have no way to determine the + // extension's real type, so we return a DynamicMessage. + return DynamicMessage.getDefaultInstance(field.getMessageType()); + } else { + return field.getDefaultValue(); + } + } else { + return value; + } + } else { + return super.getField(field); + } + } + + @Override + public int getRepeatedFieldCount(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + return extensions.getRepeatedFieldCount(field); + } else { + return super.getRepeatedFieldCount(field); + } + } + + @Override + public Object getRepeatedField(final FieldDescriptor field, + final int index) { + if (field.isExtension()) { + verifyContainingType(field); + return extensions.getRepeatedField(field, index); + } else { + return super.getRepeatedField(field, index); + } + } + + @Override + public boolean hasField(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + return extensions.hasField(field); + } else { + return super.hasField(field); + } + } @Override public BuilderType setField(final FieldDescriptor field, final Object value) { if (field.isExtension()) { - final ExtendableMessage message = internalGetResult(); - message.verifyContainingType(field); - message.extensions.setField(field, value); + verifyContainingType(field); + ensureExtensionsIsMutable(); + extensions.setField(field, value); + onChanged(); return (BuilderType) this; } else { return super.setField(field, value); @@ -679,9 +1152,10 @@ public abstract class GeneratedMessage extends AbstractMessage { @Override public BuilderType clearField(final FieldDescriptor field) { if (field.isExtension()) { - final ExtendableMessage message = internalGetResult(); - message.verifyContainingType(field); - message.extensions.clearField(field); + verifyContainingType(field); + ensureExtensionsIsMutable(); + extensions.clearField(field); + onChanged(); return (BuilderType) this; } else { return super.clearField(field); @@ -692,9 +1166,10 @@ public abstract class GeneratedMessage extends AbstractMessage { public BuilderType setRepeatedField(final FieldDescriptor field, final int index, final Object value) { if (field.isExtension()) { - final ExtendableMessage message = internalGetResult(); - message.verifyContainingType(field); - message.extensions.setRepeatedField(field, index, value); + verifyContainingType(field); + ensureExtensionsIsMutable(); + extensions.setRepeatedField(field, index, value); + onChanged(); return (BuilderType) this; } else { return super.setRepeatedField(field, index, value); @@ -705,9 +1180,10 @@ public abstract class GeneratedMessage extends AbstractMessage { public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) { if (field.isExtension()) { - final ExtendableMessage message = internalGetResult(); - message.verifyContainingType(field); - message.extensions.addRepeatedField(field, value); + verifyContainingType(field); + ensureExtensionsIsMutable(); + extensions.addRepeatedField(field, value); + onChanged(); return (BuilderType) this; } else { return super.addRepeatedField(field, value); @@ -715,17 +1191,144 @@ public abstract class GeneratedMessage extends AbstractMessage { } protected final void mergeExtensionFields(final ExtendableMessage other) { - internalGetResult().extensions.mergeFrom(other.extensions); + ensureExtensionsIsMutable(); + extensions.mergeFrom(other.extensions); + onChanged(); + } + + private void verifyContainingType(final FieldDescriptor field) { + if (field.getContainingType() != getDescriptorForType()) { + throw new IllegalArgumentException( + "FieldDescriptor does not match message type."); + } } } // ----------------------------------------------------------------- + /** + * Gets the descriptor for an extension. The implementation depends on whether + * the extension is scoped in the top level of a file or scoped in a Message. + */ + static interface ExtensionDescriptorRetriever { + FieldDescriptor getDescriptor(); + } + + /** For use by generated code only. */ + public static + GeneratedExtension + newMessageScopedGeneratedExtension(final Message scope, + final int descriptorIndex, + final Class singularType, + final Message defaultInstance) { + // For extensions scoped within a Message, we use the Message to resolve + // the outer class's descriptor, from which the extension descriptor is + // obtained. + return new GeneratedExtension( + new CachedDescriptorRetriever() { + //@Override (Java 1.6 override semantics, but we must support 1.5) + public FieldDescriptor loadDescriptor() { + return scope.getDescriptorForType().getExtensions() + .get(descriptorIndex); + } + }, + singularType, + defaultInstance, + Extension.ExtensionType.IMMUTABLE); + } + /** For use by generated code only. */ public static + GeneratedExtension + newFileScopedGeneratedExtension(final Class singularType, + final Message defaultInstance) { + // For extensions scoped within a file, we rely on the outer class's + // static initializer to call internalInit() on the extension when the + // descriptor is available. + return new GeneratedExtension( + null, // ExtensionDescriptorRetriever is initialized in internalInit(); + singularType, + defaultInstance, + Extension.ExtensionType.IMMUTABLE); + } + + private abstract static class CachedDescriptorRetriever + implements ExtensionDescriptorRetriever { + private volatile FieldDescriptor descriptor; + protected abstract FieldDescriptor loadDescriptor(); + + public FieldDescriptor getDescriptor() { + if (descriptor == null) { + synchronized (this) { + if (descriptor == null) { + descriptor = loadDescriptor(); + } + } + } + return descriptor; + } + } + + /** + * Used in proto1 generated code only. + * + * After enabling bridge, we can define proto2 extensions (the extended type + * is a proto2 mutable message) in a proto1 .proto file. For these extensions + * we should generate proto2 GeneratedExtensions. + */ + public static GeneratedExtension - newGeneratedExtension() { - return new GeneratedExtension(); + newMessageScopedGeneratedExtension( + final Message scope, final String name, + final Class singularType, final Message defaultInstance) { + // For extensions scoped within a Message, we use the Message to resolve + // the outer class's descriptor, from which the extension descriptor is + // obtained. + return new GeneratedExtension( + new CachedDescriptorRetriever() { + protected FieldDescriptor loadDescriptor() { + return scope.getDescriptorForType().findFieldByName(name); + } + }, + singularType, + defaultInstance, + Extension.ExtensionType.MUTABLE); + } + + /** + * Used in proto1 generated code only. + * + * After enabling bridge, we can define proto2 extensions (the extended type + * is a proto2 mutable message) in a proto1 .proto file. For these extensions + * we should generate proto2 GeneratedExtensions. + */ + public static + GeneratedExtension + newFileScopedGeneratedExtension( + final Class singularType, final Message defaultInstance, + final String descriptorOuterClass, final String extensionName) { + // For extensions scoped within a file, we load the descriptor outer + // class and rely on it to get the FileDescriptor which then can be + // used to obtain the extension's FieldDescriptor. + return new GeneratedExtension( + new CachedDescriptorRetriever() { + protected FieldDescriptor loadDescriptor() { + try { + Class clazz = + singularType.getClassLoader().loadClass(descriptorOuterClass); + FileDescriptor file = + (FileDescriptor) clazz.getField("descriptor").get(null); + return file.findExtensionByName(extensionName); + } catch (Exception e) { + throw new RuntimeException( + "Cannot load descriptors: " + descriptorOuterClass + + " is not a valid descriptor class name", e); + } + } + }, + singularType, + defaultInstance, + Extension.ExtensionType.MUTABLE); } /** @@ -753,87 +1356,99 @@ public abstract class GeneratedMessage extends AbstractMessage { * these static singletons as parameters to the extension accessors defined * in {@link ExtendableMessage} and {@link ExtendableBuilder}. */ - public static final class GeneratedExtension< - ContainingType extends Message, Type> { + public static class GeneratedExtension< + ContainingType extends Message, Type> extends + Extension { // TODO(kenton): Find ways to avoid using Java reflection within this // class. Also try to avoid suppressing unchecked warnings. - // We can't always initialize a GeneratedExtension when we first construct - // it due to initialization order difficulties (namely, the descriptor may - // not have been constructed yet, since it is often constructed by the - // initializer of a separate module). So, we construct an uninitialized - // GeneratedExtension once, then call internalInit() on it later. Generated - // code will always call internalInit() on all extensions as part of the - // static initialization code, and internalInit() throws an exception if - // called more than once, so this method is useless to users. - private GeneratedExtension() {} - - /** For use by generated code only. */ - public void internalInit(final FieldDescriptor descriptor, - final Class type) { - if (this.descriptor != null) { - throw new IllegalStateException("Already initialized."); - } - - if (!descriptor.isExtension()) { + // We can't always initialize the descriptor of a GeneratedExtension when + // we first construct it due to initialization order difficulties (namely, + // the descriptor may not have been constructed yet, since it is often + // constructed by the initializer of a separate module). + // + // In the case of nested extensions, we initialize the + // ExtensionDescriptorRetriever with an instance that uses the scoping + // Message's default instance to retrieve the extension's descriptor. + // + // In the case of non-nested extensions, we initialize the + // ExtensionDescriptorRetriever to null and rely on the outer class's static + // initializer to call internalInit() after the descriptor has been parsed. + GeneratedExtension(ExtensionDescriptorRetriever descriptorRetriever, + Class singularType, + Message messageDefaultInstance, + ExtensionType extensionType) { + if (Message.class.isAssignableFrom(singularType) && + !singularType.isInstance(messageDefaultInstance)) { throw new IllegalArgumentException( - "GeneratedExtension given a regular (non-extension) field."); + "Bad messageDefaultInstance for " + singularType.getName()); } + this.descriptorRetriever = descriptorRetriever; + this.singularType = singularType; + this.messageDefaultInstance = messageDefaultInstance; - this.descriptor = descriptor; - this.type = type; + if (ProtocolMessageEnum.class.isAssignableFrom(singularType)) { + this.enumValueOf = getMethodOrDie(singularType, "valueOf", + EnumValueDescriptor.class); + this.enumGetValueDescriptor = + getMethodOrDie(singularType, "getValueDescriptor"); + } else { + this.enumValueOf = null; + this.enumGetValueDescriptor = null; + } + this.extensionType = extensionType; + } - switch (descriptor.getJavaType()) { - case MESSAGE: - enumValueOf = null; - enumGetValueDescriptor = null; - messageDefaultInstance = - (Message) invokeOrDie(getMethodOrDie(type, "getDefaultInstance"), - null); - if (messageDefaultInstance == null) { - throw new IllegalStateException( - type.getName() + ".getDefaultInstance() returned null."); - } - break; - case ENUM: - enumValueOf = getMethodOrDie(type, "valueOf", - EnumValueDescriptor.class); - enumGetValueDescriptor = getMethodOrDie(type, "getValueDescriptor"); - messageDefaultInstance = null; - break; - default: - enumValueOf = null; - enumGetValueDescriptor = null; - messageDefaultInstance = null; - break; + /** For use by generated code only. */ + public void internalInit(final FieldDescriptor descriptor) { + if (descriptorRetriever != null) { + throw new IllegalStateException("Already initialized."); } + descriptorRetriever = new ExtensionDescriptorRetriever() { + //@Override (Java 1.6 override semantics, but we must support 1.5) + public FieldDescriptor getDescriptor() { + return descriptor; + } + }; } - private FieldDescriptor descriptor; - private Class type; - private Method enumValueOf; - private Method enumGetValueDescriptor; - private Message messageDefaultInstance; + private ExtensionDescriptorRetriever descriptorRetriever; + private final Class singularType; + private final Message messageDefaultInstance; + private final Method enumValueOf; + private final Method enumGetValueDescriptor; + private final ExtensionType extensionType; - public FieldDescriptor getDescriptor() { return descriptor; } + public FieldDescriptor getDescriptor() { + if (descriptorRetriever == null) { + throw new IllegalStateException( + "getDescriptor() called before internalInit()"); + } + return descriptorRetriever.getDescriptor(); + } /** * If the extension is an embedded message or group, returns the default * instance of the message. */ - @SuppressWarnings("unchecked") public Message getMessageDefaultInstance() { return messageDefaultInstance; } + protected ExtensionType getExtensionType() { + return extensionType; + } + /** * Convert from the type used by the reflection accessors to the type used * by native accessors. E.g., for enums, the reflection accessors use * EnumValueDescriptors but the native accessors use the generated enum * type. */ + // @Override @SuppressWarnings("unchecked") - private Object fromReflectionType(final Object value) { + protected Object fromReflectionType(final Object value) { + FieldDescriptor descriptor = getDescriptor(); if (descriptor.isRepeated()) { if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE || descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { @@ -855,20 +1470,16 @@ public abstract class GeneratedMessage extends AbstractMessage { * Like {@link #fromReflectionType(Object)}, but if the type is a repeated * type, this converts a single element. */ - private Object singularFromReflectionType(final Object value) { + // @Override + protected Object singularFromReflectionType(final Object value) { + FieldDescriptor descriptor = getDescriptor(); switch (descriptor.getJavaType()) { case MESSAGE: - if (type.isInstance(value)) { + if (singularType.isInstance(value)) { return value; } else { - // It seems the copy of the embedded message stored inside the - // extended message is not of the exact type the user was - // expecting. This can happen if a user defines a - // GeneratedExtension manually and gives it a different type. - // This should not happen in normal use. But, to be nice, we'll - // copy the message to whatever type the caller was expecting. return messageDefaultInstance.newBuilderForType() - .mergeFrom((Message) value).build(); + .mergeFrom((Message) value).build(); } case ENUM: return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value); @@ -883,8 +1494,10 @@ public abstract class GeneratedMessage extends AbstractMessage { * EnumValueDescriptors but the native accessors use the generated enum * type. */ + // @Override @SuppressWarnings("unchecked") - private Object toReflectionType(final Object value) { + protected Object toReflectionType(final Object value) { + FieldDescriptor descriptor = getDescriptor(); if (descriptor.isRepeated()) { if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { // Must convert the whole list. @@ -905,7 +1518,9 @@ public abstract class GeneratedMessage extends AbstractMessage { * Like {@link #toReflectionType(Object)}, but if the type is a repeated * type, this converts a single element. */ - private Object singularToReflectionType(final Object value) { + // @Override + protected Object singularToReflectionType(final Object value) { + FieldDescriptor descriptor = getDescriptor(); switch (descriptor.getJavaType()) { case ENUM: return invokeOrDie(enumGetValueDescriptor, value); @@ -913,6 +1528,34 @@ public abstract class GeneratedMessage extends AbstractMessage { return value; } } + + // @Override + public int getNumber() { + return getDescriptor().getNumber(); + } + + // @Override + public WireFormat.FieldType getLiteType() { + return getDescriptor().getLiteType(); + } + + // @Override + public boolean isRepeated() { + return getDescriptor().isRepeated(); + } + + // @Override + @SuppressWarnings("unchecked") + public Type getDefaultValue() { + if (isRepeated()) { + return (Type) Collections.emptyList(); + } + if (getDescriptor().getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + return (Type) messageDefaultInstance; + } + return (Type) singularFromReflectionType( + getDescriptor().getDefaultValue()); + } } // ================================================================= @@ -973,39 +1616,90 @@ public abstract class GeneratedMessage extends AbstractMessage { final String[] camelCaseNames, final Class messageClass, final Class builderClass) { + this(descriptor, camelCaseNames); + ensureFieldAccessorsInitialized(messageClass, builderClass); + } + + /** + * Construct a FieldAccessorTable for a particular message class without + * initializing FieldAccessors. + */ + public FieldAccessorTable( + final Descriptor descriptor, + final String[] camelCaseNames) { this.descriptor = descriptor; + this.camelCaseNames = camelCaseNames; fields = new FieldAccessor[descriptor.getFields().size()]; + oneofs = new OneofAccessor[descriptor.getOneofs().size()]; + initialized = false; + } - for (int i = 0; i < fields.length; i++) { - final FieldDescriptor field = descriptor.getFields().get(i); - if (field.isRepeated()) { - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - fields[i] = new RepeatedMessageFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass); - } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { - fields[i] = new RepeatedEnumFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass); - } else { - fields[i] = new RepeatedFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass); + /** + * Ensures the field accessors are initialized. This method is thread-safe. + * + * @param messageClass The message type. + * @param builderClass The builder type. + * @return this + */ + public FieldAccessorTable ensureFieldAccessorsInitialized( + Class messageClass, + Class builderClass) { + if (initialized) { return this; } + synchronized (this) { + if (initialized) { return this; } + int fieldsSize = fields.length; + for (int i = 0; i < fieldsSize; i++) { + FieldDescriptor field = descriptor.getFields().get(i); + String containingOneofCamelCaseName = null; + if (field.getContainingOneof() != null) { + containingOneofCamelCaseName = + camelCaseNames[fieldsSize + field.getContainingOneof().getIndex()]; } - } else { - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - fields[i] = new SingularMessageFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass); - } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { - fields[i] = new SingularEnumFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass); + if (field.isRepeated()) { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + fields[i] = new RepeatedMessageFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { + fields[i] = new RepeatedEnumFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } else { + fields[i] = new RepeatedFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } } else { - fields[i] = new SingularFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass); + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + fields[i] = new SingularMessageFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass, + containingOneofCamelCaseName); + } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { + fields[i] = new SingularEnumFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass, + containingOneofCamelCaseName); + } else { + fields[i] = new SingularFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass, + containingOneofCamelCaseName); + } } } + + int oneofsSize = oneofs.length; + for (int i = 0; i < oneofsSize; i++) { + oneofs[i] = new OneofAccessor( + descriptor, camelCaseNames[i + fieldsSize], + messageClass, builderClass); + } + initialized = true; + camelCaseNames = null; + return this; } } private final Descriptor descriptor; private final FieldAccessor[] fields; + private String[] camelCaseNames; + private final OneofAccessor[] oneofs; + private volatile boolean initialized; /** Get the FieldAccessor for a particular field. */ private FieldAccessor getField(final FieldDescriptor field) { @@ -1021,21 +1715,93 @@ public abstract class GeneratedMessage extends AbstractMessage { return fields[field.getIndex()]; } + /** Get the OneofAccessor for a particular oneof. */ + private OneofAccessor getOneof(final OneofDescriptor oneof) { + if (oneof.getContainingType() != descriptor) { + throw new IllegalArgumentException( + "OneofDescriptor does not match message type."); + } + return oneofs[oneof.getIndex()]; + } + /** * Abstract interface that provides access to a single field. This is * implemented differently depending on the field type and cardinality. */ private interface FieldAccessor { Object get(GeneratedMessage message); + Object get(GeneratedMessage.Builder builder); void set(Builder builder, Object value); Object getRepeated(GeneratedMessage message, int index); + Object getRepeated(GeneratedMessage.Builder builder, int index); void setRepeated(Builder builder, int index, Object value); void addRepeated(Builder builder, Object value); boolean has(GeneratedMessage message); + boolean has(GeneratedMessage.Builder builder); int getRepeatedCount(GeneratedMessage message); + int getRepeatedCount(GeneratedMessage.Builder builder); void clear(Builder builder); Message.Builder newBuilder(); + Message.Builder getBuilder(GeneratedMessage.Builder builder); + } + + /** OneofAccessor provides access to a single oneof. */ + private static class OneofAccessor { + OneofAccessor( + final Descriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { + this.descriptor = descriptor; + caseMethod = + getMethodOrDie(messageClass, "get" + camelCaseName + "Case"); + caseMethodBuilder = + getMethodOrDie(builderClass, "get" + camelCaseName + "Case"); + clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + } + + private final Descriptor descriptor; + private final Method caseMethod; + private final Method caseMethodBuilder; + private final Method clearMethod; + + public boolean has(final GeneratedMessage message) { + if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) { + return false; + } + return true; + } + + public boolean has(GeneratedMessage.Builder builder) { + if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) { + return false; + } + return true; + } + + public FieldDescriptor get(final GeneratedMessage message) { + int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); + if (fieldNumber > 0) { + return descriptor.findFieldByNumber(fieldNumber); + } + return null; + } + + public FieldDescriptor get(GeneratedMessage.Builder builder) { + int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); + if (fieldNumber > 0) { + return descriptor.findFieldByNumber(fieldNumber); + } + return null; + } + + public void clear(final Builder builder) { + invokeOrDie(clearMethod, builder); + } + } + + private static boolean supportFieldPresence(FileDescriptor file) { + return true; } // --------------------------------------------------------------- @@ -1044,27 +1810,57 @@ public abstract class GeneratedMessage extends AbstractMessage { SingularFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, - final Class builderClass) { + final Class builderClass, + final String containingOneofCamelCaseName) { + field = descriptor; + isOneofField = descriptor.getContainingOneof() != null; + hasHasMethod = supportFieldPresence(descriptor.getFile()) + || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE); getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); + getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName); type = getMethod.getReturnType(); setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type); hasMethod = - getMethodOrDie(messageClass, "has" + camelCaseName); + hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null; + hasMethodBuilder = + hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null; clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + caseMethod = isOneofField ? getMethodOrDie( + messageClass, "get" + containingOneofCamelCaseName + "Case") : null; + caseMethodBuilder = isOneofField ? getMethodOrDie( + builderClass, "get" + containingOneofCamelCaseName + "Case") : null; } // Note: We use Java reflection to call public methods rather than // access private fields directly as this avoids runtime security // checks. - protected final Class type; + protected final Class type; protected final Method getMethod; + protected final Method getMethodBuilder; protected final Method setMethod; protected final Method hasMethod; + protected final Method hasMethodBuilder; protected final Method clearMethod; + protected final Method caseMethod; + protected final Method caseMethodBuilder; + protected final FieldDescriptor field; + protected final boolean isOneofField; + protected final boolean hasHasMethod; + + private int getOneofFieldNumber(final GeneratedMessage message) { + return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); + } + + private int getOneofFieldNumber(final GeneratedMessage.Builder builder) { + return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); + } public Object get(final GeneratedMessage message) { return invokeOrDie(getMethod, message); } + public Object get(GeneratedMessage.Builder builder) { + return invokeOrDie(getMethodBuilder, builder); + } public void set(final Builder builder, final Object value) { invokeOrDie(setMethod, builder, value); } @@ -1073,6 +1869,10 @@ public abstract class GeneratedMessage extends AbstractMessage { throw new UnsupportedOperationException( "getRepeatedField() called on a singular field."); } + public Object getRepeated(GeneratedMessage.Builder builder, int index) { + throw new UnsupportedOperationException( + "getRepeatedField() called on a singular field."); + } public void setRepeated(final Builder builder, final int index, final Object value) { throw new UnsupportedOperationException( @@ -1083,12 +1883,31 @@ public abstract class GeneratedMessage extends AbstractMessage { "addRepeatedField() called on a singular field."); } public boolean has(final GeneratedMessage message) { + if (!hasHasMethod) { + if (isOneofField) { + return getOneofFieldNumber(message) == field.getNumber(); + } + return !get(message).equals(field.getDefaultValue()); + } return (Boolean) invokeOrDie(hasMethod, message); } + public boolean has(GeneratedMessage.Builder builder) { + if (!hasHasMethod) { + if (isOneofField) { + return getOneofFieldNumber(builder) == field.getNumber(); + } + return !get(builder).equals(field.getDefaultValue()); + } + return (Boolean) invokeOrDie(hasMethodBuilder, builder); + } public int getRepeatedCount(final GeneratedMessage message) { throw new UnsupportedOperationException( "getRepeatedFieldSize() called on a singular field."); } + public int getRepeatedCount(GeneratedMessage.Builder builder) { + throw new UnsupportedOperationException( + "getRepeatedFieldSize() called on a singular field."); + } public void clear(final Builder builder) { invokeOrDie(clearMethod, builder); } @@ -1096,48 +1915,63 @@ public abstract class GeneratedMessage extends AbstractMessage { throw new UnsupportedOperationException( "newBuilderForField() called on a non-Message type."); } + public Message.Builder getBuilder(GeneratedMessage.Builder builder) { + throw new UnsupportedOperationException( + "getFieldBuilder() called on a non-Message type."); + } } private static class RepeatedFieldAccessor implements FieldAccessor { + protected final Class type; + protected final Method getMethod; + protected final Method getMethodBuilder; + protected final Method getRepeatedMethod; + protected final Method getRepeatedMethodBuilder; + protected final Method setRepeatedMethod; + protected final Method addRepeatedMethod; + protected final Method getCountMethod; + protected final Method getCountMethodBuilder; + protected final Method clearMethod; + RepeatedFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, final Class builderClass) { getMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "List"); - + getMethodBuilder = getMethodOrDie(builderClass, + "get" + camelCaseName + "List"); getRepeatedMethod = - getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); + getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); + getRepeatedMethodBuilder = + getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE); type = getRepeatedMethod.getReturnType(); setRepeatedMethod = - getMethodOrDie(builderClass, "set" + camelCaseName, - Integer.TYPE, type); + getMethodOrDie(builderClass, "set" + camelCaseName, + Integer.TYPE, type); addRepeatedMethod = - getMethodOrDie(builderClass, "add" + camelCaseName, type); + getMethodOrDie(builderClass, "add" + camelCaseName, type); getCountMethod = - getMethodOrDie(messageClass, "get" + camelCaseName + "Count"); + getMethodOrDie(messageClass, "get" + camelCaseName + "Count"); + getCountMethodBuilder = + getMethodOrDie(builderClass, "get" + camelCaseName + "Count"); clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); } - protected final Class type; - protected final Method getMethod; - protected final Method getRepeatedMethod; - protected final Method setRepeatedMethod; - protected final Method addRepeatedMethod; - protected final Method getCountMethod; - protected final Method clearMethod; - public Object get(final GeneratedMessage message) { return invokeOrDie(getMethod, message); } + public Object get(GeneratedMessage.Builder builder) { + return invokeOrDie(getMethodBuilder, builder); + } public void set(final Builder builder, final Object value) { // Add all the elements individually. This serves two purposes: // 1) Verifies that each element has the correct type. // 2) Insures that the caller cannot modify the list later on and // have the modifications be reflected in the message. clear(builder); - for (final Object element : (List) value) { + for (final Object element : (List) value) { addRepeated(builder, element); } } @@ -1145,6 +1979,9 @@ public abstract class GeneratedMessage extends AbstractMessage { final int index) { return invokeOrDie(getRepeatedMethod, message, index); } + public Object getRepeated(GeneratedMessage.Builder builder, int index) { + return invokeOrDie(getRepeatedMethodBuilder, builder, index); + } public void setRepeated(final Builder builder, final int index, final Object value) { invokeOrDie(setRepeatedMethod, builder, index, value); @@ -1154,11 +1991,18 @@ public abstract class GeneratedMessage extends AbstractMessage { } public boolean has(final GeneratedMessage message) { throw new UnsupportedOperationException( - "hasField() called on a singular field."); + "hasField() called on a repeated field."); + } + public boolean has(GeneratedMessage.Builder builder) { + throw new UnsupportedOperationException( + "hasField() called on a repeated field."); } public int getRepeatedCount(final GeneratedMessage message) { return (Integer) invokeOrDie(getCountMethod, message); } + public int getRepeatedCount(GeneratedMessage.Builder builder) { + return (Integer) invokeOrDie(getCountMethodBuilder, builder); + } public void clear(final Builder builder) { invokeOrDie(clearMethod, builder); } @@ -1166,6 +2010,10 @@ public abstract class GeneratedMessage extends AbstractMessage { throw new UnsupportedOperationException( "newBuilderForField() called on a non-Message type."); } + public Message.Builder getBuilder(GeneratedMessage.Builder builder) { + throw new UnsupportedOperationException( + "getFieldBuilder() called on a non-Message type."); + } } // --------------------------------------------------------------- @@ -1175,8 +2023,9 @@ public abstract class GeneratedMessage extends AbstractMessage { SingularEnumFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, - final Class builderClass) { - super(descriptor, camelCaseName, messageClass, builderClass); + final Class builderClass, + final String containingOneofCamelCaseName) { + super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName); valueOfMethod = getMethodOrDie(type, "valueOf", EnumValueDescriptor.class); @@ -1191,6 +2040,12 @@ public abstract class GeneratedMessage extends AbstractMessage { public Object get(final GeneratedMessage message) { return invokeOrDie(getValueDescriptorMethod, super.get(message)); } + + @Override + public Object get(final GeneratedMessage.Builder builder) { + return invokeOrDie(getValueDescriptorMethod, super.get(builder)); + } + @Override public void set(final Builder builder, final Object value) { super.set(builder, invokeOrDie(valueOfMethod, null, value)); @@ -1223,6 +2078,17 @@ public abstract class GeneratedMessage extends AbstractMessage { } return Collections.unmodifiableList(newList); } + + @Override + @SuppressWarnings("unchecked") + public Object get(final GeneratedMessage.Builder builder) { + final List newList = new ArrayList(); + for (final Object element : (List) super.get(builder)) { + newList.add(invokeOrDie(getValueDescriptorMethod, element)); + } + return Collections.unmodifiableList(newList); + } + @Override public Object getRepeated(final GeneratedMessage message, final int index) { @@ -1230,6 +2096,12 @@ public abstract class GeneratedMessage extends AbstractMessage { super.getRepeated(message, index)); } @Override + public Object getRepeated(final GeneratedMessage.Builder builder, + final int index) { + return invokeOrDie(getValueDescriptorMethod, + super.getRepeated(builder, index)); + } + @Override public void setRepeated(final Builder builder, final int index, final Object value) { super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, @@ -1248,13 +2120,17 @@ public abstract class GeneratedMessage extends AbstractMessage { SingularMessageFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, - final Class builderClass) { - super(descriptor, camelCaseName, messageClass, builderClass); + final Class builderClass, + final String containingOneofCamelCaseName) { + super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName); newBuilderMethod = getMethodOrDie(type, "newBuilder"); + getBuilderMethodBuilder = + getMethodOrDie(builderClass, "get" + camelCaseName + "Builder"); } private final Method newBuilderMethod; + private final Method getBuilderMethodBuilder; private Object coerceType(final Object value) { if (type.isInstance(value)) { @@ -1265,7 +2141,7 @@ public abstract class GeneratedMessage extends AbstractMessage { // DynamicMessage -- we should accept it. In this case we can make // a copy of the message. return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) - .mergeFrom((Message) value).build(); + .mergeFrom((Message) value).buildPartial(); } } @@ -1277,6 +2153,10 @@ public abstract class GeneratedMessage extends AbstractMessage { public Message.Builder newBuilder() { return (Message.Builder) invokeOrDie(newBuilderMethod, null); } + @Override + public Message.Builder getBuilder(GeneratedMessage.Builder builder) { + return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder); + } } private static final class RepeatedMessageFieldAccessor @@ -1320,4 +2200,14 @@ public abstract class GeneratedMessage extends AbstractMessage { } } } + + /** + * Replaces this object in the output stream with a serialized form. + * Part of Java's serialization magic. Generated sub-classes must override + * this method by calling {@code return super.writeReplace();} + * @return a SerializedForm of this message + */ + protected Object writeReplace() throws ObjectStreamException { + return new GeneratedMessageLite.SerializedForm(this); + } } diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java index 9cdd4e9..8c70505 100644 --- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java +++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java @@ -31,6 +31,11 @@ package com.google.protobuf; import java.io.IOException; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -41,8 +46,39 @@ import java.util.Map; * * @author kenton@google.com Kenton Varda */ -public abstract class GeneratedMessageLite extends AbstractMessageLite { - protected GeneratedMessageLite() {} +public abstract class GeneratedMessageLite extends AbstractMessageLite + implements Serializable { + private static final long serialVersionUID = 1L; + + protected GeneratedMessageLite() { + } + + protected GeneratedMessageLite(Builder builder) { + } + + public Parser getParserForType() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + + /** + * Called by subclasses to parse an unknown field. + * @return {@code true} unless the tag is an end-group tag. + */ + protected boolean parseUnknownField( + CodedInputStream input, + CodedOutputStream unknownFieldsCodedOutput, + ExtensionRegistryLite extensionRegistry, + int tag) throws IOException { + return input.skipField(tag, unknownFieldsCodedOutput); + } + + /** + * Used by parsing constructors in generated classes. + */ + protected void makeExtensionsImmutable() { + // Noop for messages without extensions. + } @SuppressWarnings("unchecked") public abstract static class Builder { protected Builder() {} + //@Override (Java 1.6 override semantics, but we must support 1.5) + public BuilderType clear() { + unknownFields = ByteString.EMPTY; + return (BuilderType) this; + } + // This is implemented here only to work around an apparent bug in the // Java compiler and/or build system. See bug #1898463. The mere presence // of this dummy clone() implementation makes it go away. @@ -66,35 +108,73 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite { public abstract MessageType getDefaultInstanceForType(); /** - * Get the message being built. We don't just pass this to the - * constructor because it becomes null when build() is called. - */ - protected abstract MessageType internalGetResult(); - - /** * Called by subclasses to parse an unknown field. * @return {@code true} unless the tag is an end-group tag. */ protected boolean parseUnknownField( - final CodedInputStream input, - final ExtensionRegistryLite extensionRegistry, - final int tag) throws IOException { - return input.skipField(tag); + CodedInputStream input, + CodedOutputStream unknownFieldsCodedOutput, + ExtensionRegistryLite extensionRegistry, + int tag) throws IOException { + return input.skipField(tag, unknownFieldsCodedOutput); } + + public final ByteString getUnknownFields() { + return unknownFields; + } + + public final BuilderType setUnknownFields(final ByteString unknownFields) { + this.unknownFields = unknownFields; + return (BuilderType) this; + } + + private ByteString unknownFields = ByteString.EMPTY; } + // ================================================================= // Extensions-related stuff /** + * Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}. + */ + public interface ExtendableMessageOrBuilder< + MessageType extends ExtendableMessage> extends MessageLiteOrBuilder { + + /** Check if a singular extension is present. */ + boolean hasExtension( + GeneratedExtension extension); + + /** Get the number of elements in a repeated extension. */ + int getExtensionCount( + GeneratedExtension> extension); + + /** Get the value of an extension. */ + Type getExtension(GeneratedExtension extension); + + /** Get one element of a repeated extension. */ + Type getExtension( + GeneratedExtension> extension, + int index); + } + + /** * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}. */ public abstract static class ExtendableMessage< MessageType extends ExtendableMessage> - extends GeneratedMessageLite { - protected ExtendableMessage() {} - private final FieldSet extensions = - FieldSet.newFieldSet(); + extends GeneratedMessageLite + implements ExtendableMessageOrBuilder { + + private final FieldSet extensions; + + protected ExtendableMessage() { + this.extensions = FieldSet.newFieldSet(); + } + + protected ExtendableMessage(ExtendableBuilder builder) { + this.extensions = builder.buildExtensions(); + } private void verifyExtensionContainingType( final GeneratedExtension extension) { @@ -108,13 +188,15 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite { } /** Check if a singular extension is present. */ - public final boolean hasExtension( - final GeneratedExtension extension) { + //@Override (Java 1.6 override semantics, but we must support 1.5) + public final boolean hasExtension( + final GeneratedExtension extension) { verifyExtensionContainingType(extension); return extensions.hasField(extension.descriptor); } /** Get the number of elements in a repeated extension. */ + //@Override (Java 1.6 override semantics, but we must support 1.5) public final int getExtensionCount( final GeneratedExtension> extension) { verifyExtensionContainingType(extension); @@ -122,6 +204,7 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite { } /** Get the value of an extension. */ + //@Override (Java 1.6 override semantics, but we must support 1.5) @SuppressWarnings("unchecked") public final Type getExtension( final GeneratedExtension extension) { @@ -130,17 +213,19 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite { if (value == null) { return extension.defaultValue; } else { - return (Type) value; + return (Type) extension.fromFieldSetType(value); } } /** Get one element of a repeated extension. */ + //@Override (Java 1.6 override semantics, but we must support 1.5) @SuppressWarnings("unchecked") public final Type getExtension( final GeneratedExtension> extension, final int index) { verifyExtensionContainingType(extension); - return (Type) extensions.getRepeatedField(extension.descriptor, index); + return (Type) extension.singularFromFieldSetType( + extensions.getRepeatedField(extension.descriptor, index)); } /** Called by subclasses to check if all extensions are initialized. */ @@ -149,6 +234,34 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite { } /** + * Called by subclasses to parse an unknown field or an extension. + * @return {@code true} unless the tag is an end-group tag. + */ + @Override + protected boolean parseUnknownField( + CodedInputStream input, + CodedOutputStream unknownFieldsCodedOutput, + ExtensionRegistryLite extensionRegistry, + int tag) throws IOException { + return GeneratedMessageLite.parseUnknownField( + extensions, + getDefaultInstanceForType(), + input, + unknownFieldsCodedOutput, + extensionRegistry, + tag); + } + + + /** + * Used by parsing constructors in generated classes. + */ + @Override + protected void makeExtensionsImmutable() { + extensions.makeImmutable(); + } + + /** * Used by subclasses to serialize extensions. Extension ranges may be * interleaved with field numbers, but we must write them in canonical * (sorted by field number) order. ExtensionWriter helps us write @@ -214,53 +327,111 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite { public abstract static class ExtendableBuilder< MessageType extends ExtendableMessage, BuilderType extends ExtendableBuilder> - extends Builder { + extends Builder + implements ExtendableMessageOrBuilder { protected ExtendableBuilder() {} - // This is implemented here only to work around an apparent bug in the - // Java compiler and/or build system. See bug #1898463. The mere presence - // of this dummy clone() implementation makes it go away. - @Override - public BuilderType clone() { - throw new UnsupportedOperationException( - "This is supposed to be overridden by subclasses."); + private FieldSet extensions = FieldSet.emptySet(); + private boolean extensionsIsMutable; + + // For immutable message conversion. + void internalSetExtensionSet(FieldSet extensions) { + this.extensions = extensions; } @Override - protected abstract MessageType internalGetResult(); + public BuilderType clear() { + extensions.clear(); + extensionsIsMutable = false; + return super.clear(); + } - /** Check if a singular extension is present. */ - public final boolean hasExtension( + private void ensureExtensionsIsMutable() { + if (!extensionsIsMutable) { + extensions = extensions.clone(); + extensionsIsMutable = true; + } + } + + /** + * Called by the build code path to create a copy of the extensions for + * building the message. + */ + private FieldSet buildExtensions() { + extensions.makeImmutable(); + extensionsIsMutable = false; + return extensions; + } + + private void verifyExtensionContainingType( final GeneratedExtension extension) { - return internalGetResult().hasExtension(extension); + if (extension.getContainingTypeDefaultInstance() != + getDefaultInstanceForType()) { + // This can only happen if someone uses unchecked operations. + throw new IllegalArgumentException( + "This extension is for a different message type. Please make " + + "sure that you are not suppressing any generics type warnings."); + } + } + + /** Check if a singular extension is present. */ + //@Override (Java 1.6 override semantics, but we must support 1.5) + public final boolean hasExtension( + final GeneratedExtension extension) { + verifyExtensionContainingType(extension); + return extensions.hasField(extension.descriptor); } /** Get the number of elements in a repeated extension. */ + //@Override (Java 1.6 override semantics, but we must support 1.5) public final int getExtensionCount( final GeneratedExtension> extension) { - return internalGetResult().getExtensionCount(extension); + verifyExtensionContainingType(extension); + return extensions.getRepeatedFieldCount(extension.descriptor); } /** Get the value of an extension. */ + //@Override (Java 1.6 override semantics, but we must support 1.5) + @SuppressWarnings("unchecked") public final Type getExtension( final GeneratedExtension extension) { - return internalGetResult().getExtension(extension); + verifyExtensionContainingType(extension); + final Object value = extensions.getField(extension.descriptor); + if (value == null) { + return extension.defaultValue; + } else { + return (Type) extension.fromFieldSetType(value); + } } /** Get one element of a repeated extension. */ + @SuppressWarnings("unchecked") + //@Override (Java 1.6 override semantics, but we must support 1.5) public final Type getExtension( final GeneratedExtension> extension, final int index) { - return internalGetResult().getExtension(extension, index); + verifyExtensionContainingType(extension); + return (Type) extension.singularFromFieldSetType( + extensions.getRepeatedField(extension.descriptor, index)); + } + + // This is implemented here only to work around an apparent bug in the + // Java compiler and/or build system. See bug #1898463. The mere presence + // of this dummy clone() implementation makes it go away. + @Override + public BuilderType clone() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); } /** Set the value of an extension. */ public final BuilderType setExtension( final GeneratedExtension extension, final Type value) { - final ExtendableMessage message = internalGetResult(); - message.verifyExtensionContainingType(extension); - message.extensions.setField(extension.descriptor, value); + verifyExtensionContainingType(extension); + ensureExtensionsIsMutable(); + extensions.setField(extension.descriptor, + extension.toFieldSetType(value)); return (BuilderType) this; } @@ -268,9 +439,10 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite { public final BuilderType setExtension( final GeneratedExtension> extension, final int index, final Type value) { - final ExtendableMessage message = internalGetResult(); - message.verifyExtensionContainingType(extension); - message.extensions.setRepeatedField(extension.descriptor, index, value); + verifyExtensionContainingType(extension); + ensureExtensionsIsMutable(); + extensions.setRepeatedField(extension.descriptor, index, + extension.singularToFieldSetType(value)); return (BuilderType) this; } @@ -278,141 +450,177 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite { public final BuilderType addExtension( final GeneratedExtension> extension, final Type value) { - final ExtendableMessage message = internalGetResult(); - message.verifyExtensionContainingType(extension); - message.extensions.addRepeatedField(extension.descriptor, value); + verifyExtensionContainingType(extension); + ensureExtensionsIsMutable(); + extensions.addRepeatedField(extension.descriptor, + extension.singularToFieldSetType(value)); return (BuilderType) this; } /** Clear an extension. */ public final BuilderType clearExtension( final GeneratedExtension extension) { - final ExtendableMessage message = internalGetResult(); - message.verifyExtensionContainingType(extension); - message.extensions.clearField(extension.descriptor); + verifyExtensionContainingType(extension); + ensureExtensionsIsMutable(); + extensions.clearField(extension.descriptor); return (BuilderType) this; } + /** Called by subclasses to check if all extensions are initialized. */ + protected boolean extensionsAreInitialized() { + return extensions.isInitialized(); + } + /** * Called by subclasses to parse an unknown field or an extension. * @return {@code true} unless the tag is an end-group tag. */ @Override protected boolean parseUnknownField( - final CodedInputStream input, - final ExtensionRegistryLite extensionRegistry, - final int tag) throws IOException { - final FieldSet extensions = - ((ExtendableMessage) internalGetResult()).extensions; - - final int wireType = WireFormat.getTagWireType(tag); - final int fieldNumber = WireFormat.getTagFieldNumber(tag); - - final GeneratedExtension extension = - extensionRegistry.findLiteExtensionByNumber( - getDefaultInstanceForType(), fieldNumber); - - boolean unknown = false; - boolean packed = false; - if (extension == null) { - unknown = true; // Unknown field. - } else if (wireType == FieldSet.getWireFormatForFieldType( - extension.descriptor.getLiteType(), - false /* isPacked */)) { - packed = false; // Normal, unpacked value. - } else if (extension.descriptor.isRepeated && - extension.descriptor.type.isPackable() && - wireType == FieldSet.getWireFormatForFieldType( - extension.descriptor.getLiteType(), - true /* isPacked */)) { - packed = true; // Packed value. - } else { - unknown = true; // Wrong wire type. - } + CodedInputStream input, + CodedOutputStream unknownFieldsCodedOutput, + ExtensionRegistryLite extensionRegistry, + int tag) throws IOException { + ensureExtensionsIsMutable(); + return GeneratedMessageLite.parseUnknownField( + extensions, + getDefaultInstanceForType(), + input, + unknownFieldsCodedOutput, + extensionRegistry, + tag); + } - if (unknown) { // Unknown field or wrong wire type. Skip. - return input.skipField(tag); - } + protected final void mergeExtensionFields(final MessageType other) { + ensureExtensionsIsMutable(); + extensions.mergeFrom(((ExtendableMessage) other).extensions); + } + } - if (packed) { - final int length = input.readRawVarint32(); - final int limit = input.pushLimit(length); - if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) { - while (input.getBytesUntilLimit() > 0) { - final int rawValue = input.readEnum(); - final Object value = - extension.descriptor.getEnumType().findValueByNumber(rawValue); - if (value == null) { - // If the number isn't recognized as a valid value for this - // enum, drop it (don't even add it to unknownFields). - return true; - } - extensions.addRepeatedField(extension.descriptor, value); - } - } else { - while (input.getBytesUntilLimit() > 0) { - final Object value = - FieldSet.readPrimitiveField(input, - extension.descriptor.getLiteType()); - extensions.addRepeatedField(extension.descriptor, value); + // ----------------------------------------------------------------- + + /** + * Parse an unknown field or an extension. + * @return {@code true} unless the tag is an end-group tag. + */ + private static + boolean parseUnknownField( + FieldSet extensions, + MessageType defaultInstance, + CodedInputStream input, + CodedOutputStream unknownFieldsCodedOutput, + ExtensionRegistryLite extensionRegistry, + int tag) throws IOException { + int wireType = WireFormat.getTagWireType(tag); + int fieldNumber = WireFormat.getTagFieldNumber(tag); + + GeneratedExtension extension = + extensionRegistry.findLiteExtensionByNumber( + defaultInstance, fieldNumber); + + boolean unknown = false; + boolean packed = false; + if (extension == null) { + unknown = true; // Unknown field. + } else if (wireType == FieldSet.getWireFormatForFieldType( + extension.descriptor.getLiteType(), + false /* isPacked */)) { + packed = false; // Normal, unpacked value. + } else if (extension.descriptor.isRepeated && + extension.descriptor.type.isPackable() && + wireType == FieldSet.getWireFormatForFieldType( + extension.descriptor.getLiteType(), + true /* isPacked */)) { + packed = true; // Packed value. + } else { + unknown = true; // Wrong wire type. + } + + if (unknown) { // Unknown field or wrong wire type. Skip. + return input.skipField(tag, unknownFieldsCodedOutput); + } + + if (packed) { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) { + while (input.getBytesUntilLimit() > 0) { + int rawValue = input.readEnum(); + Object value = + extension.descriptor.getEnumType().findValueByNumber(rawValue); + if (value == null) { + // If the number isn't recognized as a valid value for this + // enum, drop it (don't even add it to unknownFields). + return true; } + extensions.addRepeatedField(extension.descriptor, + extension.singularToFieldSetType(value)); } - input.popLimit(limit); } else { - final Object value; - switch (extension.descriptor.getLiteJavaType()) { - case MESSAGE: { - MessageLite.Builder subBuilder = null; - if (!extension.descriptor.isRepeated()) { - MessageLite existingValue = - (MessageLite) extensions.getField(extension.descriptor); - if (existingValue != null) { - subBuilder = existingValue.toBuilder(); - } - } - if (subBuilder == null) { - subBuilder = extension.messageDefaultInstance.newBuilderForType(); - } - if (extension.descriptor.getLiteType() == - WireFormat.FieldType.GROUP) { - input.readGroup(extension.getNumber(), - subBuilder, extensionRegistry); - } else { - input.readMessage(subBuilder, extensionRegistry); + while (input.getBytesUntilLimit() > 0) { + Object value = + FieldSet.readPrimitiveField(input, + extension.descriptor.getLiteType(), + /*checkUtf8=*/ false); + extensions.addRepeatedField(extension.descriptor, value); + } + } + input.popLimit(limit); + } else { + Object value; + switch (extension.descriptor.getLiteJavaType()) { + case MESSAGE: { + MessageLite.Builder subBuilder = null; + if (!extension.descriptor.isRepeated()) { + MessageLite existingValue = + (MessageLite) extensions.getField(extension.descriptor); + if (existingValue != null) { + subBuilder = existingValue.toBuilder(); } - value = subBuilder.build(); - break; } - case ENUM: - final int rawValue = input.readEnum(); - value = extension.descriptor.getEnumType() - .findValueByNumber(rawValue); - // If the number isn't recognized as a valid value for this enum, - // drop it. - if (value == null) { - return true; - } - break; - default: - value = FieldSet.readPrimitiveField(input, - extension.descriptor.getLiteType()); - break; - } - - if (extension.descriptor.isRepeated()) { - extensions.addRepeatedField(extension.descriptor, value); - } else { - extensions.setField(extension.descriptor, value); + if (subBuilder == null) { + subBuilder = extension.getMessageDefaultInstance() + .newBuilderForType(); + } + if (extension.descriptor.getLiteType() == + WireFormat.FieldType.GROUP) { + input.readGroup(extension.getNumber(), + subBuilder, extensionRegistry); + } else { + input.readMessage(subBuilder, extensionRegistry); + } + value = subBuilder.build(); + break; } + case ENUM: + int rawValue = input.readEnum(); + value = extension.descriptor.getEnumType() + .findValueByNumber(rawValue); + // If the number isn't recognized as a valid value for this enum, + // write it to unknown fields object. + if (value == null) { + unknownFieldsCodedOutput.writeRawVarint32(tag); + unknownFieldsCodedOutput.writeUInt32NoTag(rawValue); + return true; + } + break; + default: + value = FieldSet.readPrimitiveField(input, + extension.descriptor.getLiteType(), + /*checkUtf8=*/ false); + break; } - return true; + if (extension.descriptor.isRepeated()) { + extensions.addRepeatedField(extension.descriptor, + extension.singularToFieldSetType(value)); + } else { + extensions.setField(extension.descriptor, + extension.singularToFieldSetType(value)); + } } - protected final void mergeExtensionFields(final MessageType other) { - ((ExtendableMessage) internalGetResult()).extensions.mergeFrom( - ((ExtendableMessage) other).extensions); - } + return true; } // ----------------------------------------------------------------- @@ -420,14 +628,50 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite { /** For use by generated code only. */ public static GeneratedExtension - newGeneratedExtension() { - return new GeneratedExtension(); + newSingularGeneratedExtension( + final ContainingType containingTypeDefaultInstance, + final Type defaultValue, + final MessageLite messageDefaultInstance, + final Internal.EnumLiteMap enumTypeMap, + final int number, + final WireFormat.FieldType type, + final Class singularType) { + return new GeneratedExtension( + containingTypeDefaultInstance, + defaultValue, + messageDefaultInstance, + new ExtensionDescriptor(enumTypeMap, number, type, + false /* isRepeated */, + false /* isPacked */), + singularType); } - private static final class ExtensionDescriptor + /** For use by generated code only. */ + public static + GeneratedExtension + newRepeatedGeneratedExtension( + final ContainingType containingTypeDefaultInstance, + final MessageLite messageDefaultInstance, + final Internal.EnumLiteMap enumTypeMap, + final int number, + final WireFormat.FieldType type, + final boolean isPacked, + final Class singularType) { + @SuppressWarnings("unchecked") // Subclasses ensure Type is a List + Type emptyList = (Type) Collections.emptyList(); + return new GeneratedExtension( + containingTypeDefaultInstance, + emptyList, + messageDefaultInstance, + new ExtensionDescriptor( + enumTypeMap, number, type, true /* isRepeated */, isPacked), + singularType); + } + + static final class ExtensionDescriptor implements FieldSet.FieldDescriptorLite< ExtensionDescriptor> { - private ExtensionDescriptor( + ExtensionDescriptor( final Internal.EnumLiteMap enumTypeMap, final int number, final WireFormat.FieldType type, @@ -440,11 +684,11 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite { this.isPacked = isPacked; } - private final Internal.EnumLiteMap enumTypeMap; - private final int number; - private final WireFormat.FieldType type; - private final boolean isRepeated; - private final boolean isPacked; + final Internal.EnumLiteMap enumTypeMap; + final int number; + final WireFormat.FieldType type; + final boolean isRepeated; + final boolean isPacked; public int getNumber() { return number; @@ -476,72 +720,103 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite { return ((Builder) to).mergeFrom((GeneratedMessageLite) from); } + public int compareTo(ExtensionDescriptor other) { return number - other.number; } } + // ================================================================= + + /** Calls Class.getMethod and throws a RuntimeException if it fails. */ + @SuppressWarnings("unchecked") + static Method getMethodOrDie(Class clazz, String name, Class... params) { + try { + return clazz.getMethod(name, params); + } catch (NoSuchMethodException e) { + throw new RuntimeException( + "Generated message class \"" + clazz.getName() + + "\" missing method \"" + name + "\".", e); + } + } + + /** Calls invoke and throws a RuntimeException if it fails. */ + static Object invokeOrDie(Method method, Object object, Object... params) { + try { + return method.invoke(object, params); + } catch (IllegalAccessException e) { + throw new RuntimeException( + "Couldn't use Java reflection to implement protocol message " + + "reflection.", e); + } catch (InvocationTargetException e) { + final Throwable cause = e.getCause(); + if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } else if (cause instanceof Error) { + throw (Error) cause; + } else { + throw new RuntimeException( + "Unexpected exception thrown by generated accessor method.", cause); + } + } + } + /** * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}. * * Users should ignore the contents of this class and only use objects of * this type as parameters to extension accessors and ExtensionRegistry.add(). */ - public static final class GeneratedExtension< + public static class GeneratedExtension< ContainingType extends MessageLite, Type> { - // We can't always initialize a GeneratedExtension when we first construct - // it due to initialization order difficulties (namely, the default - // instances may not have been constructed yet). So, we construct an - // uninitialized GeneratedExtension once, then call internalInit() on it - // later. Generated code will always call internalInit() on all extensions - // as part of the static initialization code, and internalInit() throws an - // exception if called more than once, so this method is useless to users. - private GeneratedExtension() {} - - private void internalInit( + + /** + * Create a new isntance with the given parameters. + * + * The last parameter {@code singularType} is only needed for enum types. + * We store integer values for enum types in a {@link ExtendableMessage} + * and use Java reflection to convert an integer value back into a concrete + * enum object. + */ + GeneratedExtension( final ContainingType containingTypeDefaultInstance, final Type defaultValue, final MessageLite messageDefaultInstance, - final ExtensionDescriptor descriptor) { + final ExtensionDescriptor descriptor, + Class singularType) { + // Defensive checks to verify the correct initialization order of + // GeneratedExtensions and their related GeneratedMessages. + if (containingTypeDefaultInstance == null) { + throw new IllegalArgumentException( + "Null containingTypeDefaultInstance"); + } + if (descriptor.getLiteType() == WireFormat.FieldType.MESSAGE && + messageDefaultInstance == null) { + throw new IllegalArgumentException( + "Null messageDefaultInstance"); + } this.containingTypeDefaultInstance = containingTypeDefaultInstance; this.defaultValue = defaultValue; this.messageDefaultInstance = messageDefaultInstance; this.descriptor = descriptor; - } - - /** For use by generated code only. */ - public void internalInitSingular( - final ContainingType containingTypeDefaultInstance, - final Type defaultValue, - final MessageLite messageDefaultInstance, - final Internal.EnumLiteMap enumTypeMap, - final int number, - final WireFormat.FieldType type) { - internalInit( - containingTypeDefaultInstance, defaultValue, messageDefaultInstance, - new ExtensionDescriptor(enumTypeMap, number, type, - false /* isRepeated */, false /* isPacked */)); - } - /** For use by generated code only. */ - public void internalInitRepeated( - final ContainingType containingTypeDefaultInstance, - final MessageLite messageDefaultInstance, - final Internal.EnumLiteMap enumTypeMap, - final int number, - final WireFormat.FieldType type, - final boolean isPacked) { - internalInit( - containingTypeDefaultInstance, (Type) Collections.emptyList(), - messageDefaultInstance, - new ExtensionDescriptor( - enumTypeMap, number, type, true /* isRepeated */, isPacked)); + // Use Java reflection to invoke the static method {@code valueOf} of + // enum types in order to convert integers to concrete enum objects. + this.singularType = singularType; + if (Internal.EnumLite.class.isAssignableFrom(singularType)) { + this.enumValueOf = getMethodOrDie( + singularType, "valueOf", int.class); + } else { + this.enumValueOf = null; + } } - private ContainingType containingTypeDefaultInstance; - private Type defaultValue; - private MessageLite messageDefaultInstance; - private ExtensionDescriptor descriptor; + final ContainingType containingTypeDefaultInstance; + final Type defaultValue; + final MessageLite messageDefaultInstance; + final ExtensionDescriptor descriptor; + final Class singularType; + final Method enumValueOf; /** * Default instance of the type being extended, used to identify that type. @@ -555,12 +830,120 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite { return descriptor.getNumber(); } + /** - * If the extension is an embedded message, this is the default instance of - * that type. + * If the extension is an embedded message or group, returns the default + * instance of the message. */ public MessageLite getMessageDefaultInstance() { return messageDefaultInstance; } + + @SuppressWarnings("unchecked") + Object fromFieldSetType(final Object value) { + if (descriptor.isRepeated()) { + if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) { + final List result = new ArrayList(); + for (final Object element : (List) value) { + result.add(singularFromFieldSetType(element)); + } + return result; + } else { + return value; + } + } else { + return singularFromFieldSetType(value); + } + } + + Object singularFromFieldSetType(final Object value) { + if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) { + return invokeOrDie(enumValueOf, null, (Integer) value); + } else { + return value; + } + } + + @SuppressWarnings("unchecked") + Object toFieldSetType(final Object value) { + if (descriptor.isRepeated()) { + if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) { + final List result = new ArrayList(); + for (final Object element : (List) value) { + result.add(singularToFieldSetType(element)); + } + return result; + } else { + return value; + } + } else { + return singularToFieldSetType(value); + } + } + + Object singularToFieldSetType(final Object value) { + if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) { + return ((Internal.EnumLite) value).getNumber(); + } else { + return value; + } + } + } + + /** + * A serialized (serializable) form of the generated message. Stores the + * message as a class name and a byte array. + */ + static final class SerializedForm implements Serializable { + private static final long serialVersionUID = 0L; + + private String messageClassName; + private byte[] asBytes; + + /** + * Creates the serialized form by calling {@link com.google.protobuf.MessageLite#toByteArray}. + * @param regularForm the message to serialize + */ + SerializedForm(MessageLite regularForm) { + messageClassName = regularForm.getClass().getName(); + asBytes = regularForm.toByteArray(); + } + + /** + * When read from an ObjectInputStream, this method converts this object + * back to the regular form. Part of Java's serialization magic. + * @return a GeneratedMessage of the type that was serialized + */ + @SuppressWarnings("unchecked") + protected Object readResolve() throws ObjectStreamException { + try { + Class messageClass = Class.forName(messageClassName); + Method newBuilder = messageClass.getMethod("newBuilder"); + MessageLite.Builder builder = + (MessageLite.Builder) newBuilder.invoke(null); + builder.mergeFrom(asBytes); + return builder.buildPartial(); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Unable to find proto buffer class", e); + } catch (NoSuchMethodException e) { + throw new RuntimeException("Unable to find newBuilder method", e); + } catch (IllegalAccessException e) { + throw new RuntimeException("Unable to call newBuilder method", e); + } catch (InvocationTargetException e) { + throw new RuntimeException("Error calling newBuilder", e.getCause()); + } catch (InvalidProtocolBufferException e) { + throw new RuntimeException("Unable to understand proto buffer", e); + } + } + } + + /** + * Replaces this object in the output stream with a serialized form. + * Part of Java's serialization magic. Generated sub-classes must override + * this method by calling {@code return super.writeReplace();} + * @return a SerializedForm of this message + */ + protected Object writeReplace() throws ObjectStreamException { + return new SerializedForm(this); } } diff --git a/java/src/main/java/com/google/protobuf/Internal.java b/java/src/main/java/com/google/protobuf/Internal.java index 965465e..5c234c5 100644 --- a/java/src/main/java/com/google/protobuf/Internal.java +++ b/java/src/main/java/com/google/protobuf/Internal.java @@ -30,7 +30,11 @@ package com.google.protobuf; +import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.List; /** * The classes contained within are used internally by the Protocol Buffer @@ -98,6 +102,112 @@ public class Internal { "Java VM does not support a standard character set.", e); } } + /** + * Helper called by generated code to construct default values for bytes + * fields. + *

+ * This is like {@link #bytesDefaultValue}, but returns a byte array. + */ + public static byte[] byteArrayDefaultValue(String bytes) { + try { + return bytes.getBytes("ISO-8859-1"); + } catch (UnsupportedEncodingException e) { + // This should never happen since all JVMs are required to implement + // ISO-8859-1. + throw new IllegalStateException( + "Java VM does not support a standard character set.", e); + } + } + + /** + * Helper called by generated code to construct default values for bytes + * fields. + *

+ * This is like {@link #bytesDefaultValue}, but returns a ByteBuffer. + */ + public static ByteBuffer byteBufferDefaultValue(String bytes) { + return ByteBuffer.wrap(byteArrayDefaultValue(bytes)); + } + + /** + * Create a new ByteBuffer and copy all the content of {@code source} + * ByteBuffer to the new ByteBuffer. The new ByteBuffer's limit and + * capacity will be source.capacity(), and its position will be 0. + * Note that the state of {@code source} ByteBuffer won't be changed. + */ + public static ByteBuffer copyByteBuffer(ByteBuffer source) { + // Make a duplicate of the source ByteBuffer and read data from the + // duplicate. This is to avoid affecting the source ByteBuffer's state. + ByteBuffer temp = source.duplicate(); + // We want to copy all the data in the source ByteBuffer, not just the + // remaining bytes. + temp.clear(); + ByteBuffer result = ByteBuffer.allocate(temp.capacity()); + result.put(temp); + result.clear(); + return result; + } + + /** + * Helper called by generated code to determine if a byte array is a valid + * UTF-8 encoded string such that the original bytes can be converted to + * a String object and then back to a byte array round tripping the bytes + * without loss. More precisely, returns {@code true} whenever: + *

   {@code
+   * Arrays.equals(byteString.toByteArray(),
+   *     new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
+   * }
+ * + *

This method rejects "overlong" byte sequences, as well as + * 3-byte sequences that would map to a surrogate character, in + * accordance with the restricted definition of UTF-8 introduced in + * Unicode 3.1. Note that the UTF-8 decoder included in Oracle's + * JDK has been modified to also reject "overlong" byte sequences, + * but currently (2011) still accepts 3-byte surrogate character + * byte sequences. + * + *

See the Unicode Standard,
+ * Table 3-6. UTF-8 Bit Distribution,
+ * Table 3-7. Well Formed UTF-8 Byte Sequences. + * + *

As of 2011-02, this method simply returns the result of {@link + * ByteString#isValidUtf8()}. Calling that method directly is preferred. + * + * @param byteString the string to check + * @return whether the byte array is round trippable + */ + public static boolean isValidUtf8(ByteString byteString) { + return byteString.isValidUtf8(); + } + + /** + * Like {@link #isValidUtf8(ByteString)} but for byte arrays. + */ + public static boolean isValidUtf8(byte[] byteArray) { + return Utf8.isValidUtf8(byteArray); + } + + /** + * Helper method to get the UTF-8 bytes of a string. + */ + public static byte[] toByteArray(String value) { + try { + return value.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("UTF-8 not supported?", e); + } + } + + /** + * Helper method to convert a byte array to a string using UTF-8 encoding. + */ + public static String toStringUtf8(byte[] bytes) { + try { + return new String(bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("UTF-8 not supported?", e); + } + } /** * Interface for an enum value or value descriptor, to be used in FieldSet. @@ -118,4 +228,164 @@ public class Internal { public interface EnumLiteMap { T findValueByNumber(int number); } + + /** + * Helper method for implementing {@link MessageLite#hashCode()} for longs. + * @see Long#hashCode() + */ + public static int hashLong(long n) { + return (int) (n ^ (n >>> 32)); + } + + /** + * Helper method for implementing {@link MessageLite#hashCode()} for + * booleans. + * @see Boolean#hashCode() + */ + public static int hashBoolean(boolean b) { + return b ? 1231 : 1237; + } + + /** + * Helper method for implementing {@link MessageLite#hashCode()} for enums. + *

+ * This is needed because {@link java.lang.Enum#hashCode()} is final, but we + * need to use the field number as the hash code to ensure compatibility + * between statically and dynamically generated enum objects. + */ + public static int hashEnum(EnumLite e) { + return e.getNumber(); + } + + /** + * Helper method for implementing {@link MessageLite#hashCode()} for + * enum lists. + */ + public static int hashEnumList(List list) { + int hash = 1; + for (EnumLite e : list) { + hash = 31 * hash + hashEnum(e); + } + return hash; + } + + /** + * Helper method for implementing {@link MessageLite#equals()} for bytes field. + */ + public static boolean equals(List a, List b) { + if (a.size() != b.size()) return false; + for (int i = 0; i < a.size(); ++i) { + if (!Arrays.equals(a.get(i), b.get(i))) { + return false; + } + } + return true; + } + + /** + * Helper method for implementing {@link MessageLite#hashCode()} for bytes field. + */ + public static int hashCode(List list) { + int hash = 1; + for (byte[] bytes : list) { + hash = 31 * hash + hashCode(bytes); + } + return hash; + } + + /** + * Helper method for implementing {@link MessageLite#hashCode()} for bytes field. + */ + public static int hashCode(byte[] bytes) { + // The hash code for a byte array should be the same as the hash code for a + // ByteString with the same content. This is to ensure that the generated + // hashCode() method will return the same value as the pure reflection + // based hashCode() method. + return LiteralByteString.hashCode(bytes); + } + + /** + * Helper method for implementing {@link MessageLite#equals()} for bytes + * field. + */ + public static boolean equalsByteBuffer(ByteBuffer a, ByteBuffer b) { + if (a.capacity() != b.capacity()) { + return false; + } + // ByteBuffer.equals() will only compare the remaining bytes, but we want to + // compare all the content. + return a.duplicate().clear().equals(b.duplicate().clear()); + } + + /** + * Helper method for implementing {@link MessageLite#equals()} for bytes + * field. + */ + public static boolean equalsByteBuffer( + List a, List b) { + if (a.size() != b.size()) { + return false; + } + for (int i = 0; i < a.size(); ++i) { + if (!equalsByteBuffer(a.get(i), b.get(i))) { + return false; + } + } + return true; + } + + /** + * Helper method for implementing {@link MessageLite#hashCode()} for bytes + * field. + */ + public static int hashCodeByteBuffer(List list) { + int hash = 1; + for (ByteBuffer bytes : list) { + hash = 31 * hash + hashCodeByteBuffer(bytes); + } + return hash; + } + + private static final int DEFAULT_BUFFER_SIZE = 4096; + + /** + * Helper method for implementing {@link MessageLite#hashCode()} for bytes + * field. + */ + public static int hashCodeByteBuffer(ByteBuffer bytes) { + if (bytes.hasArray()) { + // Fast path. + int h = LiteralByteString.hashCode(bytes.capacity(), bytes.array(), + bytes.arrayOffset(), bytes.capacity()); + return h == 0 ? 1 : h; + } else { + // Read the data into a temporary byte array before calculating the + // hash value. + final int bufferSize = bytes.capacity() > DEFAULT_BUFFER_SIZE + ? DEFAULT_BUFFER_SIZE : bytes.capacity(); + final byte[] buffer = new byte[bufferSize]; + final ByteBuffer duplicated = bytes.duplicate(); + duplicated.clear(); + int h = bytes.capacity(); + while (duplicated.remaining() > 0) { + final int length = duplicated.remaining() <= bufferSize ? + duplicated.remaining() : bufferSize; + duplicated.get(buffer, 0, length); + h = LiteralByteString.hashCode(h, buffer, 0, length); + } + return h == 0 ? 1 : h; + } + } + + /** + * An empty byte array constant used in generated code. + */ + public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + + /** + * An empty byte array constant used in generated code. + */ + public static final ByteBuffer EMPTY_BYTE_BUFFER = + ByteBuffer.wrap(EMPTY_BYTE_ARRAY); + } diff --git a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java index 90f7ffb..ae320be 100644 --- a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java +++ b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java @@ -40,11 +40,32 @@ import java.io.IOException; */ public class InvalidProtocolBufferException extends IOException { private static final long serialVersionUID = -1616151763072450476L; + private MessageLite unfinishedMessage = null; public InvalidProtocolBufferException(final String description) { super(description); } + /** + * Attaches an unfinished message to the exception to support best-effort + * parsing in {@code Parser} interface. + * + * @return this + */ + public InvalidProtocolBufferException setUnfinishedMessage( + MessageLite unfinishedMessage) { + this.unfinishedMessage = unfinishedMessage; + return this; + } + + /** + * Returns the unfinished message attached to the exception, or null if + * no message is attached. + */ + public MessageLite getUnfinishedMessage() { + return unfinishedMessage; + } + static InvalidProtocolBufferException truncatedMessage() { return new InvalidProtocolBufferException( "While parsing a protocol message, the input ended unexpectedly " + @@ -90,4 +111,12 @@ public class InvalidProtocolBufferException extends IOException { "Protocol message was too large. May be malicious. " + "Use CodedInputStream.setSizeLimit() to increase the size limit."); } + + static InvalidProtocolBufferException parseFailure() { + return new InvalidProtocolBufferException("Failed to parse the message."); + } + + static InvalidProtocolBufferException invalidUtf8() { + return new InvalidProtocolBufferException("Protocol message had invalid UTF-8."); + } } diff --git a/java/src/main/java/com/google/protobuf/LazyField.java b/java/src/main/java/com/google/protobuf/LazyField.java new file mode 100644 index 0000000..0cb65d6 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/LazyField.java @@ -0,0 +1,154 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.util.Iterator; +import java.util.Map.Entry; + +/** + * LazyField encapsulates the logic of lazily parsing message fields. It stores + * the message in a ByteString initially and then parse it on-demand. + * + * Most of key methods are implemented in {@link LazyFieldLite} but this class + * can contain default instance of the message to provide {@code hashCode()}, + * {@code euqals()} and {@code toString()}. + * + * @author xiangl@google.com (Xiang Li) + */ +public class LazyField extends LazyFieldLite { + + /** + * Carry a message's default instance which is used by {@code hashCode()}, {@code euqals()} and + * {@code toString()}. + */ + private final MessageLite defaultInstance; + + public LazyField(MessageLite defaultInstance, + ExtensionRegistryLite extensionRegistry, ByteString bytes) { + super(extensionRegistry, bytes); + + this.defaultInstance = defaultInstance; + } + + @Override + public boolean containsDefaultInstance() { + return super.containsDefaultInstance() || value == defaultInstance; + } + + public MessageLite getValue() { + return getValue(defaultInstance); + } + + @Override + public int hashCode() { + return getValue().hashCode(); + } + + @Override + public boolean equals(Object obj) { + return getValue().equals(obj); + } + + @Override + public String toString() { + return getValue().toString(); + } + + // ==================================================== + + /** + * LazyEntry and LazyIterator are used to encapsulate the LazyField, when + * users iterate all fields from FieldSet. + */ + static class LazyEntry implements Entry { + private Entry entry; + + private LazyEntry(Entry entry) { + this.entry = entry; + } + + // @Override + public K getKey() { + return entry.getKey(); + } + + // @Override + public Object getValue() { + LazyField field = entry.getValue(); + if (field == null) { + return null; + } + return field.getValue(); + } + + public LazyField getField() { + return entry.getValue(); + } + + // @Override + public Object setValue(Object value) { + if (!(value instanceof MessageLite)) { + throw new IllegalArgumentException( + "LazyField now only used for MessageSet, " + + "and the value of MessageSet must be an instance of MessageLite"); + } + return entry.getValue().setValue((MessageLite) value); + } + } + + static class LazyIterator implements Iterator> { + private Iterator> iterator; + + public LazyIterator(Iterator> iterator) { + this.iterator = iterator; + } + + // @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @SuppressWarnings("unchecked") + // @Override + public Entry next() { + Entry entry = iterator.next(); + if (entry.getValue() instanceof LazyField) { + return new LazyEntry((Entry) entry); + } + return (Entry) entry; + } + + // @Override + public void remove() { + iterator.remove(); + } + } +} diff --git a/java/src/main/java/com/google/protobuf/LazyFieldLite.java b/java/src/main/java/com/google/protobuf/LazyFieldLite.java new file mode 100644 index 0000000..2c4d0dc --- /dev/null +++ b/java/src/main/java/com/google/protobuf/LazyFieldLite.java @@ -0,0 +1,176 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.io.IOException; + +/** + * LazyFieldLite encapsulates the logic of lazily parsing message fields. It stores + * the message in a ByteString initially and then parse it on-demand. + * + * LazyField is thread-compatible e.g. concurrent read are safe, however, + * synchronizations are needed under read/write situations. + * + * This class is internal implementation detail, so you don't need to use it directly. + * + * @author xiangl@google.com (Xiang Li) + */ +public class LazyFieldLite { + private ByteString bytes; + private ExtensionRegistryLite extensionRegistry; + private volatile boolean isDirty = false; + + protected volatile MessageLite value; + + public LazyFieldLite(ExtensionRegistryLite extensionRegistry, ByteString bytes) { + this.extensionRegistry = extensionRegistry; + this.bytes = bytes; + } + + public LazyFieldLite() { + } + + public static LazyFieldLite fromValue(MessageLite value) { + LazyFieldLite lf = new LazyFieldLite(); + lf.setValue(value); + return lf; + } + + public boolean containsDefaultInstance() { + return value == null && bytes == null; + } + + public void clear() { + bytes = null; + value = null; + extensionRegistry = null; + isDirty = true; + } + + /** + * Returns message instance. At first time, serialized data is parsed by + * {@code defaultInstance.getParserForType()}. + * + * @param defaultInstance its message's default instance. It's also used to get parser for the + * message type. + */ + public MessageLite getValue(MessageLite defaultInstance) { + ensureInitialized(defaultInstance); + return value; + } + + /** + * LazyField is not thread-safe for write access. Synchronizations are needed + * under read/write situations. + */ + public MessageLite setValue(MessageLite value) { + MessageLite originalValue = this.value; + this.value = value; + bytes = null; + isDirty = true; + return originalValue; + } + + public void merge(LazyFieldLite value) { + if (value.containsDefaultInstance()) { + return; + } + + if (bytes == null) { + this.bytes = value.bytes; + } else { + this.bytes.concat(value.toByteString()); + } + isDirty = false; + } + + public void setByteString(ByteString bytes, ExtensionRegistryLite extensionRegistry) { + this.bytes = bytes; + this.extensionRegistry = extensionRegistry; + isDirty = false; + } + + public ExtensionRegistryLite getExtensionRegistry() { + return extensionRegistry; + } + + /** + * Due to the optional field can be duplicated at the end of serialized + * bytes, which will make the serialized size changed after LazyField + * parsed. Be careful when using this method. + */ + public int getSerializedSize() { + if (isDirty) { + return value.getSerializedSize(); + } + return bytes.size(); + } + + public ByteString toByteString() { + if (!isDirty) { + return bytes; + } + synchronized (this) { + if (!isDirty) { + return bytes; + } + if (value == null) { + bytes = ByteString.EMPTY; + } else { + bytes = value.toByteString(); + } + isDirty = false; + return bytes; + } + } + + protected void ensureInitialized(MessageLite defaultInstance) { + if (value != null) { + return; + } + synchronized (this) { + if (value != null) { + return; + } + try { + if (bytes != null) { + value = defaultInstance.getParserForType() + .parseFrom(bytes, extensionRegistry); + } else { + value = defaultInstance; + } + } catch (IOException e) { + // TODO(xiangl): Refactory the API to support the exception thrown from + // lazily load messages. + } + } + } +} diff --git a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java new file mode 100644 index 0000000..5599c7f --- /dev/null +++ b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java @@ -0,0 +1,367 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.util.Arrays; +import java.util.List; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.RandomAccess; + +/** + * An implementation of {@link LazyStringList} that wraps an ArrayList. Each + * element is one of String, ByteString, or byte[]. It caches the last one + * requested which is most likely the one needed next. This minimizes memory + * usage while satisfying the most common use cases. + *

+ * Note that this implementation is not synchronized. + * If multiple threads access an ArrayList instance concurrently, + * and at least one of the threads modifies the list structurally, it + * must be synchronized externally. (A structural modification is + * any operation that adds or deletes one or more elements, or explicitly + * resizes the backing array; merely setting the value of an element is not + * a structural modification.) This is typically accomplished by + * synchronizing on some object that naturally encapsulates the list. + *

+ * If the implementation is accessed via concurrent reads, this is thread safe. + * Conversions are done in a thread safe manner. It's possible that the + * conversion may happen more than once if two threads attempt to access the + * same element and the modifications were not visible to each other, but this + * will not result in any corruption of the list or change in behavior other + * than performance. + * + * @author jonp@google.com (Jon Perlow) + */ +public class LazyStringArrayList extends AbstractList + implements LazyStringList, RandomAccess { + + public static final LazyStringList EMPTY = + new LazyStringArrayList().getUnmodifiableView(); + + private final List list; + + public LazyStringArrayList() { + list = new ArrayList(); + } + + public LazyStringArrayList(LazyStringList from) { + list = new ArrayList(from.size()); + addAll(from); + } + + public LazyStringArrayList(List from) { + list = new ArrayList(from); + } + + @Override + public String get(int index) { + Object o = list.get(index); + if (o instanceof String) { + return (String) o; + } else if (o instanceof ByteString) { + ByteString bs = (ByteString) o; + String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + list.set(index, s); + } + return s; + } else { + byte[] ba = (byte[]) o; + String s = Internal.toStringUtf8(ba); + if (Internal.isValidUtf8(ba)) { + list.set(index, s); + } + return s; + } + } + + @Override + public int size() { + return list.size(); + } + + @Override + public String set(int index, String s) { + Object o = list.set(index, s); + return asString(o); + } + + @Override + public void add(int index, String element) { + list.add(index, element); + modCount++; + } + + @Override + public boolean addAll(Collection c) { + // The default implementation of AbstractCollection.addAll(Collection) + // delegates to add(Object). This implementation instead delegates to + // addAll(int, Collection), which makes a special case for Collections + // which are instances of LazyStringList. + return addAll(size(), c); + } + + @Override + public boolean addAll(int index, Collection c) { + // When copying from another LazyStringList, directly copy the underlying + // elements rather than forcing each element to be decoded to a String. + Collection collection = c instanceof LazyStringList + ? ((LazyStringList) c).getUnderlyingElements() : c; + boolean ret = list.addAll(index, collection); + modCount++; + return ret; + } + + // @Override + public boolean addAllByteString(Collection values) { + boolean ret = list.addAll(values); + modCount++; + return ret; + } + + // @Override + public boolean addAllByteArray(Collection c) { + boolean ret = list.addAll(c); + modCount++; + return ret; + } + + @Override + public String remove(int index) { + Object o = list.remove(index); + modCount++; + return asString(o); + } + + @Override + public void clear() { + list.clear(); + modCount++; + } + + // @Override + public void add(ByteString element) { + list.add(element); + modCount++; + } + + // @Override + public void add(byte[] element) { + list.add(element); + modCount++; + } + + // @Override + public ByteString getByteString(int index) { + Object o = list.get(index); + ByteString b = asByteString(o); + if (b != o) { + list.set(index, b); + } + return b; + } + + // @Override + public byte[] getByteArray(int index) { + Object o = list.get(index); + byte[] b = asByteArray(o); + if (b != o) { + list.set(index, b); + } + return b; + } + + // @Override + public void set(int index, ByteString s) { + list.set(index, s); + } + + // @Override + public void set(int index, byte[] s) { + list.set(index, s); + } + + + private static String asString(Object o) { + if (o instanceof String) { + return (String) o; + } else if (o instanceof ByteString) { + return ((ByteString) o).toStringUtf8(); + } else { + return Internal.toStringUtf8((byte[]) o); + } + } + + private static ByteString asByteString(Object o) { + if (o instanceof ByteString) { + return (ByteString) o; + } else if (o instanceof String) { + return ByteString.copyFromUtf8((String) o); + } else { + return ByteString.copyFrom((byte[]) o); + } + } + + private static byte[] asByteArray(Object o) { + if (o instanceof byte[]) { + return (byte[]) o; + } else if (o instanceof String) { + return Internal.toByteArray((String) o); + } else { + return ((ByteString) o).toByteArray(); + } + } + + // @Override + public List getUnderlyingElements() { + return Collections.unmodifiableList(list); + } + + // @Override + public void mergeFrom(LazyStringList other) { + for (Object o : other.getUnderlyingElements()) { + if (o instanceof byte[]) { + byte[] b = (byte[]) o; + // Byte array's content is mutable so they should be copied rather than + // shared when merging from one message to another. + list.add(Arrays.copyOf(b, b.length)); + } else { + list.add(o); + } + } + } + + private static class ByteArrayListView extends AbstractList + implements RandomAccess { + private final List list; + + ByteArrayListView(List list) { + this.list = list; + } + + @Override + public byte[] get(int index) { + Object o = list.get(index); + byte[] b = asByteArray(o); + if (b != o) { + list.set(index, b); + } + return b; + } + + @Override + public int size() { + return list.size(); + } + + @Override + public byte[] set(int index, byte[] s) { + Object o = list.set(index, s); + modCount++; + return asByteArray(o); + } + + @Override + public void add(int index, byte[] s) { + list.add(index, s); + modCount++; + } + + @Override + public byte[] remove(int index) { + Object o = list.remove(index); + modCount++; + return asByteArray(o); + } + } + + // @Override + public List asByteArrayList() { + return new ByteArrayListView(list); + } + + private static class ByteStringListView extends AbstractList + implements RandomAccess { + private final List list; + + ByteStringListView(List list) { + this.list = list; + } + + @Override + public ByteString get(int index) { + Object o = list.get(index); + ByteString b = asByteString(o); + if (b != o) { + list.set(index, b); + } + return b; + } + + @Override + public int size() { + return list.size(); + } + + @Override + public ByteString set(int index, ByteString s) { + Object o = list.set(index, s); + modCount++; + return asByteString(o); + } + + @Override + public void add(int index, ByteString s) { + list.add(index, s); + modCount++; + } + + @Override + public ByteString remove(int index) { + Object o = list.remove(index); + modCount++; + return asByteString(o); + } + } + + // @Override + public List asByteStringList() { + return new ByteStringListView(list); + } + + // @Override + public LazyStringList getUnmodifiableView() { + return new UnmodifiableLazyStringList(this); + } + +} diff --git a/java/src/main/java/com/google/protobuf/LazyStringList.java b/java/src/main/java/com/google/protobuf/LazyStringList.java new file mode 100644 index 0000000..7418c92 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/LazyStringList.java @@ -0,0 +1,163 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.util.Collection; +import java.util.List; + +/** + * An interface extending {@code List} that also provides access to the + * items of the list as UTF8-encoded ByteString or byte[] objects. This is + * used by the protocol buffer implementation to support lazily converting bytes + * parsed over the wire to String objects until needed and also increases the + * efficiency of serialization if the String was never requested as the + * ByteString or byte[] is already cached. The ByteString methods are used in + * immutable API only and byte[] methods used in mutable API only for they use + * different representations for string/bytes fields. + * + * @author jonp@google.com (Jon Perlow) + */ +public interface LazyStringList extends ProtocolStringList { + + /** + * Returns the element at the specified position in this list as a ByteString. + * + * @param index index of the element to return + * @return the element at the specified position in this list + * @throws IndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + */ + ByteString getByteString(int index); + + /** + * Returns the element at the specified position in this list as byte[]. + * + * @param index index of the element to return + * @return the element at the specified position in this list + * @throws IndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + */ + byte[] getByteArray(int index); + + /** + * Appends the specified element to the end of this list (optional + * operation). + * + * @param element element to be appended to this list + * @throws UnsupportedOperationException if the add operation + * is not supported by this list + */ + void add(ByteString element); + + /** + * Appends the specified element to the end of this list (optional + * operation). + * + * @param element element to be appended to this list + * @throws UnsupportedOperationException if the add operation + * is not supported by this list + */ + void add(byte[] element); + + /** + * Replaces the element at the specified position in this list with the + * specified element (optional operation). + * + * @param index index of the element to replace + * @param element the element to be stored at the specified position + * @throws UnsupportedOperationException if the set operation + * is not supported by this list + * IndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + */ + void set(int index, ByteString element); + + /** + * Replaces the element at the specified position in this list with the + * specified element (optional operation). + * + * @param index index of the element to replace + * @param element the element to be stored at the specified position + * @throws UnsupportedOperationException if the set operation + * is not supported by this list + * IndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + */ + void set(int index, byte[] element); + + /** + * Appends all elements in the specified ByteString collection to the end of + * this list. + * + * @param c collection whose elements are to be added to this list + * @return true if this list changed as a result of the call + * @throws UnsupportedOperationException if the addAllByteString + * operation is not supported by this list + */ + boolean addAllByteString(Collection c); + + /** + * Appends all elements in the specified byte[] collection to the end of + * this list. + * + * @param c collection whose elements are to be added to this list + * @return true if this list changed as a result of the call + * @throws UnsupportedOperationException if the addAllByteArray + * operation is not supported by this list + */ + boolean addAllByteArray(Collection c); + + /** + * Returns an unmodifiable List of the underlying elements, each of which is + * either a {@code String} or its equivalent UTF-8 encoded {@code ByteString} + * or byte[]. It is an error for the caller to modify the returned + * List, and attempting to do so will result in an + * {@link UnsupportedOperationException}. + */ + List getUnderlyingElements(); + + /** + * Merges all elements from another LazyStringList into this one. This method + * differs from {@link #addAll(Collection)} on that underlying byte arrays are + * copied instead of reference shared. Immutable API doesn't need to use this + * method as byte[] is not used there at all. + */ + void mergeFrom(LazyStringList other); + + /** + * Returns a mutable view of this list. Changes to the view will be made into + * the original list. This method is used in mutable API only. + */ + List asByteArrayList(); + + /** Returns an unmodifiable view of the list. */ + LazyStringList getUnmodifiableView(); +} diff --git a/java/src/main/java/com/google/protobuf/LiteralByteString.java b/java/src/main/java/com/google/protobuf/LiteralByteString.java new file mode 100644 index 0000000..543da52 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/LiteralByteString.java @@ -0,0 +1,362 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +/** + * This class implements a {@link com.google.protobuf.ByteString} backed by a + * single array of bytes, contiguous in memory. It supports substring by + * pointing to only a sub-range of the underlying byte array, meaning that a + * substring will reference the full byte-array of the string it's made from, + * exactly as with {@link String}. + * + * @author carlanton@google.com (Carl Haverl) + */ +class LiteralByteString extends ByteString { + + protected final byte[] bytes; + + /** + * Creates a {@code LiteralByteString} backed by the given array, without + * copying. + * + * @param bytes array to wrap + */ + LiteralByteString(byte[] bytes) { + this.bytes = bytes; + } + + @Override + public byte byteAt(int index) { + // Unlike most methods in this class, this one is a direct implementation + // ignoring the potential offset because we need to do range-checking in the + // substring case anyway. + return bytes[index]; + } + + @Override + public int size() { + return bytes.length; + } + + // ================================================================= + // ByteString -> substring + + @Override + public ByteString substring(int beginIndex, int endIndex) { + if (beginIndex < 0) { + throw new IndexOutOfBoundsException( + "Beginning index: " + beginIndex + " < 0"); + } + if (endIndex > size()) { + throw new IndexOutOfBoundsException("End index: " + endIndex + " > " + + size()); + } + int substringLength = endIndex - beginIndex; + if (substringLength < 0) { + throw new IndexOutOfBoundsException( + "Beginning index larger than ending index: " + beginIndex + ", " + + endIndex); + } + + ByteString result; + if (substringLength == 0) { + result = ByteString.EMPTY; + } else { + result = new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex, + substringLength); + } + return result; + } + + // ================================================================= + // ByteString -> byte[] + + @Override + protected void copyToInternal(byte[] target, int sourceOffset, + int targetOffset, int numberToCopy) { + // Optimized form, not for subclasses, since we don't call + // getOffsetIntoBytes() or check the 'numberToCopy' parameter. + System.arraycopy(bytes, sourceOffset, target, targetOffset, numberToCopy); + } + + @Override + public void copyTo(ByteBuffer target) { + target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes + } + + @Override + public ByteBuffer asReadOnlyByteBuffer() { + ByteBuffer byteBuffer = + ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size()); + return byteBuffer.asReadOnlyBuffer(); + } + + @Override + public List asReadOnlyByteBufferList() { + // Return the ByteBuffer generated by asReadOnlyByteBuffer() as a singleton + List result = new ArrayList(1); + result.add(asReadOnlyByteBuffer()); + return result; + } + + @Override + public void writeTo(OutputStream outputStream) throws IOException { + outputStream.write(toByteArray()); + } + + @Override + void writeToInternal(OutputStream outputStream, int sourceOffset, + int numberToWrite) throws IOException { + outputStream.write(bytes, getOffsetIntoBytes() + sourceOffset, + numberToWrite); + } + + @Override + public String toString(String charsetName) + throws UnsupportedEncodingException { + return new String(bytes, getOffsetIntoBytes(), size(), charsetName); + } + + // ================================================================= + // UTF-8 decoding + + @Override + public boolean isValidUtf8() { + int offset = getOffsetIntoBytes(); + return Utf8.isValidUtf8(bytes, offset, offset + size()); + } + + @Override + protected int partialIsValidUtf8(int state, int offset, int length) { + int index = getOffsetIntoBytes() + offset; + return Utf8.partialIsValidUtf8(state, bytes, index, index + length); + } + + // ================================================================= + // equals() and hashCode() + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if (!(other instanceof ByteString)) { + return false; + } + + if (size() != ((ByteString) other).size()) { + return false; + } + if (size() == 0) { + return true; + } + + if (other instanceof LiteralByteString) { + return equalsRange((LiteralByteString) other, 0, size()); + } else if (other instanceof RopeByteString) { + return other.equals(this); + } else { + throw new IllegalArgumentException( + "Has a new type of ByteString been created? Found " + + other.getClass()); + } + } + + /** + * Check equality of the substring of given length of this object starting at + * zero with another {@code LiteralByteString} substring starting at offset. + * + * @param other what to compare a substring in + * @param offset offset into other + * @param length number of bytes to compare + * @return true for equality of substrings, else false. + */ + boolean equalsRange(LiteralByteString other, int offset, int length) { + if (length > other.size()) { + throw new IllegalArgumentException( + "Length too large: " + length + size()); + } + if (offset + length > other.size()) { + throw new IllegalArgumentException( + "Ran off end of other: " + offset + ", " + length + ", " + + other.size()); + } + + byte[] thisBytes = bytes; + byte[] otherBytes = other.bytes; + int thisLimit = getOffsetIntoBytes() + length; + for (int thisIndex = getOffsetIntoBytes(), otherIndex = + other.getOffsetIntoBytes() + offset; + (thisIndex < thisLimit); ++thisIndex, ++otherIndex) { + if (thisBytes[thisIndex] != otherBytes[otherIndex]) { + return false; + } + } + return true; + } + + /** + * Cached hash value. Intentionally accessed via a data race, which + * is safe because of the Java Memory Model's "no out-of-thin-air values" + * guarantees for ints. + */ + private int hash = 0; + + /** + * Compute the hashCode using the traditional algorithm from {@link + * ByteString}. + * + * @return hashCode value + */ + @Override + public int hashCode() { + int h = hash; + + if (h == 0) { + int size = size(); + h = partialHash(size, 0, size); + if (h == 0) { + h = 1; + } + hash = h; + } + return h; + } + + @Override + protected int peekCachedHashCode() { + return hash; + } + + @Override + protected int partialHash(int h, int offset, int length) { + return hashCode(h, bytes, getOffsetIntoBytes() + offset, length); + } + + static int hashCode(int h, byte[] bytes, int offset, int length) { + for (int i = offset; i < offset + length; i++) { + h = h * 31 + bytes[i]; + } + return h; + } + + static int hashCode(byte[] bytes) { + int h = hashCode(bytes.length, bytes, 0, bytes.length); + return h == 0 ? 1 : h; + } + + // ================================================================= + // Input stream + + @Override + public InputStream newInput() { + return new ByteArrayInputStream(bytes, getOffsetIntoBytes(), + size()); // No copy + } + + @Override + public CodedInputStream newCodedInput() { + // We trust CodedInputStream not to modify the bytes, or to give anyone + // else access to them. + return CodedInputStream.newInstance(this); + } + + // ================================================================= + // ByteIterator + + @Override + public ByteIterator iterator() { + return new LiteralByteIterator(); + } + + private class LiteralByteIterator implements ByteIterator { + private int position; + private final int limit; + + private LiteralByteIterator() { + position = 0; + limit = size(); + } + + public boolean hasNext() { + return (position < limit); + } + + public Byte next() { + // Boxing calls Byte.valueOf(byte), which does not instantiate. + return nextByte(); + } + + public byte nextByte() { + try { + return bytes[position++]; + } catch (ArrayIndexOutOfBoundsException e) { + throw new NoSuchElementException(e.getMessage()); + } + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } + + // ================================================================= + // Internal methods + + @Override + protected int getTreeDepth() { + return 0; + } + + @Override + protected boolean isBalanced() { + return true; + } + + /** + * Offset into {@code bytes[]} to use, non-zero for substrings. + * + * @return always 0 for this class + */ + protected int getOffsetIntoBytes() { + return 0; + } +} diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java index 8c29e21..19fc3b4 100644 --- a/java/src/main/java/com/google/protobuf/Message.java +++ b/java/src/main/java/com/google/protobuf/Message.java @@ -48,89 +48,33 @@ import java.util.Map; * * @author kenton@google.com Kenton Varda */ -public interface Message extends MessageLite { - /** - * Get the message's type's descriptor. This differs from the - * {@code getDescriptor()} method of generated message classes in that - * this method is an abstract method of the {@code Message} interface - * whereas {@code getDescriptor()} is a static method of a specific class. - * They return the same thing. - */ - Descriptors.Descriptor getDescriptorForType(); +public interface Message extends MessageLite, MessageOrBuilder { // (From MessageLite, re-declared here only for return type covariance.) - Message getDefaultInstanceForType(); - - /** - * Returns a collection of all the fields in this message which are set - * and their corresponding values. A singular ("required" or "optional") - * field is set iff hasField() returns true for that field. A "repeated" - * field is set iff getRepeatedFieldSize() is greater than zero. The - * values are exactly what would be returned by calling - * {@link #getField(Descriptors.FieldDescriptor)} for each field. The map - * is guaranteed to be a sorted map, so iterating over it will return fields - * in order by field number. - */ - Map getAllFields(); - - /** - * Returns true if the given field is set. This is exactly equivalent to - * calling the generated "has" accessor method corresponding to the field. - * @throws IllegalArgumentException The field is a repeated field, or - * {@code field.getContainingType() != getDescriptorForType()}. - */ - boolean hasField(Descriptors.FieldDescriptor field); - - /** - * Obtains the value of the given field, or the default value if it is - * not set. For primitive fields, the boxed primitive value is returned. - * For enum fields, the EnumValueDescriptor for the value is returend. For - * embedded message fields, the sub-message is returned. For repeated - * fields, a java.util.List is returned. - */ - Object getField(Descriptors.FieldDescriptor field); - - /** - * Gets the number of elements of a repeated field. This is exactly - * equivalent to calling the generated "Count" accessor method corresponding - * to the field. - * @throws IllegalArgumentException The field is not a repeated field, or - * {@code field.getContainingType() != getDescriptorForType()}. - */ - int getRepeatedFieldCount(Descriptors.FieldDescriptor field); - - /** - * Gets an element of a repeated field. For primitive fields, the boxed - * primitive value is returned. For enum fields, the EnumValueDescriptor - * for the value is returend. For embedded message fields, the sub-message - * is returned. - * @throws IllegalArgumentException The field is not a repeated field, or - * {@code field.getContainingType() != getDescriptorForType()}. - */ - Object getRepeatedField(Descriptors.FieldDescriptor field, int index); + Parser getParserForType(); - /** Get the {@link UnknownFieldSet} for this message. */ - UnknownFieldSet getUnknownFields(); // ----------------------------------------------------------------- // Comparison and hashing /** * Compares the specified object with this message for equality. Returns - * true if the given object is a message of the same type (as + * {@code true} if the given object is a message of the same type (as * defined by {@code getDescriptorForType()}) and has identical values for - * all of its fields. + * all of its fields. Subclasses must implement this; inheriting + * {@code Object.equals()} is incorrect. * * @param other object to be compared for equality with this message - * @return true if the specified object is equal to this message + * @return {@code true} if the specified object is equal to this message */ @Override boolean equals(Object other); /** * Returns the hash code value for this message. The hash code of a message - * is defined to be getDescriptor().hashCode() ^ map.hashCode(), - * where map is a map of field numbers to field values. + * should mix the message's type (object identity of the descriptor) with its + * contents (known and unknown field values). Subclasses must implement this; + * inheriting {@code Object.hashCode()} is incorrect. * * @return the hash code value for this message * @see Map#hashCode() @@ -143,7 +87,8 @@ public interface Message extends MessageLite { /** * Converts the message to a string in protocol buffer text format. This is - * just a trivial wrapper around {@link TextFormat#printToString(Message)}. + * just a trivial wrapper around {@link + * TextFormat#printToString(MessageOrBuilder)}. */ @Override String toString(); @@ -158,7 +103,7 @@ public interface Message extends MessageLite { /** * Abstract interface implemented by Protocol Message builders. */ - interface Builder extends MessageLite.Builder { + interface Builder extends MessageLite.Builder, MessageOrBuilder { // (From MessageLite.Builder, re-declared here only for return type // covariance.) Builder clear(); @@ -197,17 +142,6 @@ public interface Message extends MessageLite { */ Descriptors.Descriptor getDescriptorForType(); - // (From MessageLite.Builder, re-declared here only for return type - // covariance.) - Message getDefaultInstanceForType(); - - /** - * Like {@link Message#getAllFields()}. The returned map may or may not - * reflect future changes to the builder. Either way, the returned map is - * itself unmodifiable. - */ - Map getAllFields(); - /** * Create a Builder for messages of the appropriate type for the given * field. Messages built with this can then be passed to setField(), @@ -215,11 +149,23 @@ public interface Message extends MessageLite { */ Builder newBuilderForField(Descriptors.FieldDescriptor field); - /** Like {@link Message#hasField(Descriptors.FieldDescriptor)} */ - boolean hasField(Descriptors.FieldDescriptor field); - - /** Like {@link Message#getField(Descriptors.FieldDescriptor)} */ - Object getField(Descriptors.FieldDescriptor field); + /** + * Get a nested builder instance for the given field. + *

+ * Normally, we hold a reference to the immutable message object for the + * message type field. Some implementations(the generated message builders), + * however, can also hold a reference to the builder object (a nested + * builder) for the field. + *

+ * If the field is already backed up by a nested builder, the nested builder + * will be returned. Otherwise, a new field builder will be created and + * returned. The original message field (if exist) will be merged into the + * field builder, which will then be nested into its parent builder. + *

+ * NOTE: implementations that do not support nested builders will throw + * UnsupportedException. + */ + Builder getFieldBuilder(Descriptors.FieldDescriptor field); /** * Sets a field to the given value. The value must be of the correct type @@ -235,14 +181,10 @@ public interface Message extends MessageLite { Builder clearField(Descriptors.FieldDescriptor field); /** - * Like {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)} + * Clears the oneof. This is exactly equivalent to calling the generated + * "clear" accessor method corresponding to the oneof. */ - int getRepeatedFieldCount(Descriptors.FieldDescriptor field); - - /** - * Like {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)} - */ - Object getRepeatedField(Descriptors.FieldDescriptor field, int index); + Builder clearOneof(Descriptors.OneofDescriptor oneof); /** * Sets an element of a repeated field to the given value. The value must @@ -262,9 +204,6 @@ public interface Message extends MessageLite { */ Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value); - /** Get the {@link UnknownFieldSet} for this message. */ - UnknownFieldSet getUnknownFields(); - /** Set the {@link UnknownFieldSet} for this message. */ Builder setUnknownFields(UnknownFieldSet unknownFields); diff --git a/java/src/main/java/com/google/protobuf/MessageLite.java b/java/src/main/java/com/google/protobuf/MessageLite.java index cf7f39e..86be04e 100644 --- a/java/src/main/java/com/google/protobuf/MessageLite.java +++ b/java/src/main/java/com/google/protobuf/MessageLite.java @@ -64,22 +64,8 @@ import java.io.OutputStream; * * @author kenton@google.com Kenton Varda */ -public interface MessageLite { - /** - * Get an instance of the type with all fields set to their default values. - * This may or may not be a singleton. This differs from the - * {@code getDefaultInstance()} method of generated message classes in that - * this method is an abstract method of the {@code MessageLite} interface - * whereas {@code getDefaultInstance()} is a static method of a specific - * class. They return the same thing. - */ - MessageLite getDefaultInstanceForType(); +public interface MessageLite extends MessageLiteOrBuilder { - /** - * Returns true if all required fields in the message and all embedded - * messages are set, false otherwise. - */ - boolean isInitialized(); /** * Serializes the message and writes it to {@code output}. This does not @@ -93,6 +79,12 @@ public interface MessageLite { */ int getSerializedSize(); + + /** + * Gets the parser for a message of the same type as this message. + */ + Parser getParserForType(); + // ----------------------------------------------------------------- // Convenience methods. @@ -136,6 +128,7 @@ public interface MessageLite { */ void writeDelimitedTo(OutputStream output) throws IOException; + // ================================================================= // Builders @@ -153,16 +146,13 @@ public interface MessageLite { /** * Abstract interface implemented by Protocol Message builders. */ - interface Builder extends Cloneable { + interface Builder extends MessageLiteOrBuilder, Cloneable { /** Resets all fields to their default values. */ Builder clear(); /** - * Construct the final message. Once this is called, the Builder is no - * longer valid, and calling any other method will result in undefined - * behavior and may throw a NullPointerException. If you need to continue - * working with the builder after calling {@code build()}, {@code clone()} - * it first. + * Constructs the message based on the state of the Builder. Subsequent + * changes to the Builder will not affect the returned message. * @throws UninitializedMessageException The message is missing one or more * required fields (i.e. {@link #isInitialized()} returns false). * Use {@link #buildPartial()} to bypass this check. @@ -172,11 +162,7 @@ public interface MessageLite { /** * Like {@link #build()}, but does not throw an exception if the message * is missing required fields. Instead, a partial message is returned. - * Once this is called, the Builder is no longer valid, and calling any - * will result in undefined behavior and may throw a NullPointerException. - * - * If you need to continue working with the builder after calling - * {@code buildPartial()}, {@code clone()} it first. + * Subsequent changes to the Builder will not affect the returned message. */ MessageLite buildPartial(); @@ -187,14 +173,8 @@ public interface MessageLite { Builder clone(); /** - * Returns true if all required fields in the message and all embedded - * messages are set, false otherwise. - */ - boolean isInitialized(); - - /** * Parses a message of this type from the input and merges it with this - * message, as if using {@link Builder#mergeFrom(MessageLite)}. + * message. * *

Warning: This does not verify that all required fields are present in * the input message. If you call {@link #build()} without setting all @@ -204,11 +184,6 @@ public interface MessageLite { *

    *
  • Call {@link #isInitialized()} to verify that all required fields * are set before building. - *
  • Parse the message separately using one of the static - * {@code parseFrom} methods, then use {@link #mergeFrom(MessageLite)} - * to merge it with this one. {@code parseFrom} will throw an - * {@link InvalidProtocolBufferException} (an {@code IOException}) - * if some required fields are missing. *
  • Use {@code buildPartial()} to build, which ignores missing * required fields. *
@@ -230,12 +205,6 @@ public interface MessageLite { ExtensionRegistryLite extensionRegistry) throws IOException; - /** - * Get the message's type's default instance. - * See {@link MessageLite#getDefaultInstanceForType()}. - */ - MessageLite getDefaultInstanceForType(); - // --------------------------------------------------------------- // Convenience methods. @@ -243,13 +212,17 @@ public interface MessageLite { * Parse {@code data} as a message of this type and merge it with the * message being built. This is just a small wrapper around * {@link #mergeFrom(CodedInputStream)}. + * + * @return this */ Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException; /** * Parse {@code data} as a message of this type and merge it with the * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}. + * + * @return this */ Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry) @@ -259,6 +232,8 @@ public interface MessageLite { * Parse {@code data} as a message of this type and merge it with the * message being built. This is just a small wrapper around * {@link #mergeFrom(CodedInputStream)}. + * + * @return this */ Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException; @@ -266,6 +241,8 @@ public interface MessageLite { * Parse {@code data} as a message of this type and merge it with the * message being built. This is just a small wrapper around * {@link #mergeFrom(CodedInputStream)}. + * + * @return this */ Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException; @@ -273,7 +250,9 @@ public interface MessageLite { /** * Parse {@code data} as a message of this type and merge it with the * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}. + * + * @return this */ Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry) @@ -282,7 +261,9 @@ public interface MessageLite { /** * Parse {@code data} as a message of this type and merge it with the * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}. + * + * @return this */ Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) @@ -299,13 +280,17 @@ public interface MessageLite { * and {@link #mergeDelimitedFrom(InputStream)} to read it. *

* Despite usually reading the entire input, this does not close the stream. + * + * @return this */ Builder mergeFrom(InputStream input) throws IOException; /** * Parse a message of this type from {@code input} and merge it with the * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}. + * + * @return this */ Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry) @@ -318,9 +303,9 @@ public interface MessageLite { * {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in * this format. * - * @returns True if successful, or false if the stream is at EOF when the - * method starts. Any other error (including reaching EOF during - * parsing) will cause an exception to be thrown. + * @return True if successful, or false if the stream is at EOF when the + * method starts. Any other error (including reaching EOF during + * parsing) will cause an exception to be thrown. */ boolean mergeDelimitedFrom(InputStream input) throws IOException; diff --git a/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java b/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java new file mode 100644 index 0000000..05b2b16 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java @@ -0,0 +1,60 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +/** + * Base interface for methods common to {@link MessageLite} + * and {@link MessageLite.Builder} to provide type equivalency. + * + * @author jonp@google.com (Jon Perlow) + */ +public interface MessageLiteOrBuilder { + /** + * Get an instance of the type with no fields set. Because no fields are set, + * all getters for singular fields will return default values and repeated + * fields will appear empty. + * This may or may not be a singleton. This differs from the + * {@code getDefaultInstance()} method of generated message classes in that + * this method is an abstract method of the {@code MessageLite} interface + * whereas {@code getDefaultInstance()} is a static method of a specific + * class. They return the same thing. + */ + MessageLite getDefaultInstanceForType(); + + /** + * Returns true if all required fields in the message and all embedded + * messages are set, false otherwise. + * + *

See also: {@link MessageOrBuilder#getInitializationErrorString()} + */ + boolean isInitialized(); + +} diff --git a/java/src/main/java/com/google/protobuf/MessageOrBuilder.java b/java/src/main/java/com/google/protobuf/MessageOrBuilder.java new file mode 100644 index 0000000..886f5b4 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/MessageOrBuilder.java @@ -0,0 +1,143 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.util.List; +import java.util.Map; + +/** + * Base interface for methods common to {@link Message} and + * {@link Message.Builder} to provide type equivalency. + * + * @author jonp@google.com (Jon Perlow) + */ +public interface MessageOrBuilder extends MessageLiteOrBuilder { + + // (From MessageLite, re-declared here only for return type covariance.) + //@Override (Java 1.6 override semantics, but we must support 1.5) + Message getDefaultInstanceForType(); + + /** + * Returns a list of field paths (e.g. "foo.bar.baz") of required fields + * which are not set in this message. You should call + * {@link MessageLiteOrBuilder#isInitialized()} first to check if there + * are any missing fields, as that method is likely to be much faster + * than this one even when the message is fully-initialized. + */ + List findInitializationErrors(); + + /** + * Returns a comma-delimited list of required fields which are not set + * in this message object. You should call + * {@link MessageLiteOrBuilder#isInitialized()} first to check if there + * are any missing fields, as that method is likely to be much faster + * than this one even when the message is fully-initialized. + */ + String getInitializationErrorString(); + + /** + * Get the message's type's descriptor. This differs from the + * {@code getDescriptor()} method of generated message classes in that + * this method is an abstract method of the {@code Message} interface + * whereas {@code getDescriptor()} is a static method of a specific class. + * They return the same thing. + */ + Descriptors.Descriptor getDescriptorForType(); + + /** + * Returns a collection of all the fields in this message which are set + * and their corresponding values. A singular ("required" or "optional") + * field is set iff hasField() returns true for that field. A "repeated" + * field is set iff getRepeatedFieldCount() is greater than zero. The + * values are exactly what would be returned by calling + * {@link #getField(Descriptors.FieldDescriptor)} for each field. The map + * is guaranteed to be a sorted map, so iterating over it will return fields + * in order by field number. + *
+ * If this is for a builder, the returned map may or may not reflect future + * changes to the builder. Either way, the returned map is itself + * unmodifiable. + */ + Map getAllFields(); + + /** + * Returns true if the given oneof is set. + * @throws IllegalArgumentException if + * {@code oneof.getContainingType() != getDescriptorForType()}. + */ + boolean hasOneof(Descriptors.OneofDescriptor oneof); + + /** + * Obtains the FieldDescriptor if the given oneof is set. Returns null + * if no field is set. + */ + Descriptors.FieldDescriptor getOneofFieldDescriptor( + Descriptors.OneofDescriptor oneof); + + /** + * Returns true if the given field is set. This is exactly equivalent to + * calling the generated "has" accessor method corresponding to the field. + * @throws IllegalArgumentException The field is a repeated field, or + * {@code field.getContainingType() != getDescriptorForType()}. + */ + boolean hasField(Descriptors.FieldDescriptor field); + + /** + * Obtains the value of the given field, or the default value if it is + * not set. For primitive fields, the boxed primitive value is returned. + * For enum fields, the EnumValueDescriptor for the value is returned. For + * embedded message fields, the sub-message is returned. For repeated + * fields, a java.util.List is returned. + */ + Object getField(Descriptors.FieldDescriptor field); + + /** + * Gets the number of elements of a repeated field. This is exactly + * equivalent to calling the generated "Count" accessor method corresponding + * to the field. + * @throws IllegalArgumentException The field is not a repeated field, or + * {@code field.getContainingType() != getDescriptorForType()}. + */ + int getRepeatedFieldCount(Descriptors.FieldDescriptor field); + + /** + * Gets an element of a repeated field. For primitive fields, the boxed + * primitive value is returned. For enum fields, the EnumValueDescriptor + * for the value is returned. For embedded message fields, the sub-message + * is returned. + * @throws IllegalArgumentException The field is not a repeated field, or + * {@code field.getContainingType() != getDescriptorForType()}. + */ + Object getRepeatedField(Descriptors.FieldDescriptor field, int index); + + /** Get the {@link UnknownFieldSet} for this message. */ + UnknownFieldSet getUnknownFields(); +} diff --git a/java/src/main/java/com/google/protobuf/MessageReflection.java b/java/src/main/java/com/google/protobuf/MessageReflection.java new file mode 100644 index 0000000..021b9d5 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/MessageReflection.java @@ -0,0 +1,931 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import com.google.protobuf.Descriptors.FieldDescriptor; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * Reflection utility methods shared by both mutable and immutable messages. + * + * @author liujisi@google.com (Pherl Liu) + */ +class MessageReflection { + + static void writeMessageTo(Message message, CodedOutputStream output, + boolean alwaysWriteRequiredFields) + throws IOException { + final boolean isMessageSet = + message.getDescriptorForType().getOptions().getMessageSetWireFormat(); + + Map fields = message.getAllFields(); + if (alwaysWriteRequiredFields) { + fields = new TreeMap(fields); + for (final FieldDescriptor field : + message.getDescriptorForType().getFields()) { + if (field.isRequired() && !fields.containsKey(field)) { + fields.put(field, message.getField(field)); + } + } + } + for (final Map.Entry entry : + fields.entrySet()) { + final Descriptors.FieldDescriptor field = entry.getKey(); + final Object value = entry.getValue(); + if (isMessageSet && field.isExtension() && + field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE && + !field.isRepeated()) { + output.writeMessageSetExtension(field.getNumber(), (Message) value); + } else { + FieldSet.writeField(field, value, output); + } + } + + final UnknownFieldSet unknownFields = message.getUnknownFields(); + if (isMessageSet) { + unknownFields.writeAsMessageSetTo(output); + } else { + unknownFields.writeTo(output); + } + } + + static int getSerializedSize(Message message) { + int size = 0; + final boolean isMessageSet = + message.getDescriptorForType().getOptions().getMessageSetWireFormat(); + + for (final Map.Entry entry : + message.getAllFields().entrySet()) { + final Descriptors.FieldDescriptor field = entry.getKey(); + final Object value = entry.getValue(); + if (isMessageSet && field.isExtension() && + field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE && + !field.isRepeated()) { + size += CodedOutputStream.computeMessageSetExtensionSize( + field.getNumber(), (Message) value); + } else { + size += FieldSet.computeFieldSize(field, value); + } + } + + final UnknownFieldSet unknownFields = message.getUnknownFields(); + if (isMessageSet) { + size += unknownFields.getSerializedSizeAsMessageSet(); + } else { + size += unknownFields.getSerializedSize(); + } + return size; + } + + static String delimitWithCommas(List parts) { + StringBuilder result = new StringBuilder(); + for (String part : parts) { + if (result.length() > 0) { + result.append(", "); + } + result.append(part); + } + return result.toString(); + } + + @SuppressWarnings("unchecked") + static boolean isInitialized(MessageOrBuilder message) { + // Check that all required fields are present. + for (final Descriptors.FieldDescriptor field : message + .getDescriptorForType() + .getFields()) { + if (field.isRequired()) { + if (!message.hasField(field)) { + return false; + } + } + } + + // Check that embedded messages are initialized. + for (final Map.Entry entry : + message.getAllFields().entrySet()) { + final Descriptors.FieldDescriptor field = entry.getKey(); + if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + for (final Message element + : (List) entry.getValue()) { + if (!element.isInitialized()) { + return false; + } + } + } else { + if (!((Message) entry.getValue()).isInitialized()) { + return false; + } + } + } + } + + return true; + } + + private static String subMessagePrefix(final String prefix, + final Descriptors.FieldDescriptor field, + final int index) { + final StringBuilder result = new StringBuilder(prefix); + if (field.isExtension()) { + result.append('(') + .append(field.getFullName()) + .append(')'); + } else { + result.append(field.getName()); + } + if (index != -1) { + result.append('[') + .append(index) + .append(']'); + } + result.append('.'); + return result.toString(); + } + + private static void findMissingFields(final MessageOrBuilder message, + final String prefix, + final List results) { + for (final Descriptors.FieldDescriptor field : + message.getDescriptorForType().getFields()) { + if (field.isRequired() && !message.hasField(field)) { + results.add(prefix + field.getName()); + } + } + + for (final Map.Entry entry : + message.getAllFields().entrySet()) { + final Descriptors.FieldDescriptor field = entry.getKey(); + final Object value = entry.getValue(); + + if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + int i = 0; + for (final Object element : (List) value) { + findMissingFields((MessageOrBuilder) element, + subMessagePrefix(prefix, field, i++), + results); + } + } else { + if (message.hasField(field)) { + findMissingFields((MessageOrBuilder) value, + subMessagePrefix(prefix, field, -1), + results); + } + } + } + } + } + + /** + * Populates {@code this.missingFields} with the full "path" of each missing + * required field in the given message. + */ + static List findMissingFields( + final MessageOrBuilder message) { + final List results = new ArrayList(); + findMissingFields(message, "", results); + return results; + } + + static interface MergeTarget { + enum ContainerType { + MESSAGE, EXTENSION_SET + } + + /** + * Returns the descriptor for the target. + */ + public Descriptors.Descriptor getDescriptorForType(); + + public ContainerType getContainerType(); + + public ExtensionRegistry.ExtensionInfo findExtensionByName( + ExtensionRegistry registry, String name); + + public ExtensionRegistry.ExtensionInfo findExtensionByNumber( + ExtensionRegistry registry, Descriptors.Descriptor containingType, + int fieldNumber); + + /** + * Obtains the value of the given field, or the default value if it is not + * set. For primitive fields, the boxed primitive value is returned. For + * enum fields, the EnumValueDescriptor for the value is returned. For + * embedded message fields, the sub-message is returned. For repeated + * fields, a java.util.List is returned. + */ + public Object getField(Descriptors.FieldDescriptor field); + + /** + * Returns true if the given field is set. This is exactly equivalent to + * calling the generated "has" accessor method corresponding to the field. + * + * @throws IllegalArgumentException The field is a repeated field, or {@code + * field.getContainingType() != getDescriptorForType()}. + */ + boolean hasField(Descriptors.FieldDescriptor field); + + /** + * Sets a field to the given value. The value must be of the correct type + * for this field, i.e. the same type that + * {@link Message#getField(Descriptors.FieldDescriptor)} + * would return. + */ + MergeTarget setField(Descriptors.FieldDescriptor field, Object value); + + /** + * Clears the field. This is exactly equivalent to calling the generated + * "clear" accessor method corresponding to the field. + */ + MergeTarget clearField(Descriptors.FieldDescriptor field); + + /** + * Sets an element of a repeated field to the given value. The value must + * be of the correct type for this field, i.e. the same type that {@link + * Message#getRepeatedField(Descriptors.FieldDescriptor, int)} would return. + * + * @throws IllegalArgumentException The field is not a repeated field, or + * {@code field.getContainingType() != + * getDescriptorForType()}. + */ + MergeTarget setRepeatedField(Descriptors.FieldDescriptor field, + int index, Object value); + + /** + * Like {@code setRepeatedField}, but appends the value as a new element. + * + * @throws IllegalArgumentException The field is not a repeated field, or + * {@code field.getContainingType() != + * getDescriptorForType()}. + */ + MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, + Object value); + + /** + * Returns true if the given oneof is set. + * + * @throws IllegalArgumentException if + * {@code oneof.getContainingType() != getDescriptorForType()}. + */ + boolean hasOneof(Descriptors.OneofDescriptor oneof); + + /** + * Clears the oneof. This is exactly equivalent to calling the generated + * "clear" accessor method corresponding to the oneof. + */ + MergeTarget clearOneof(Descriptors.OneofDescriptor oneof); + + /** + * Obtains the FieldDescriptor if the given oneof is set. Returns null + * if no field is set. + */ + Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof); + + /** + * Parse the input stream into a sub field group defined based on either + * FieldDescriptor or the default instance. + */ + Object parseGroup(CodedInputStream input, ExtensionRegistryLite registry, + Descriptors.FieldDescriptor descriptor, Message defaultInstance) + throws IOException; + + /** + * Parse the input stream into a sub field message defined based on either + * FieldDescriptor or the default instance. + */ + Object parseMessage(CodedInputStream input, ExtensionRegistryLite registry, + Descriptors.FieldDescriptor descriptor, Message defaultInstance) + throws IOException; + + /** + * Parse from a ByteString into a sub field message defined based on either + * FieldDescriptor or the default instance. There isn't a varint indicating + * the length of the message at the beginning of the input ByteString. + */ + Object parseMessageFromBytes( + ByteString bytes, ExtensionRegistryLite registry, + Descriptors.FieldDescriptor descriptor, Message defaultInstance) + throws IOException; + + /** + * Read a primitive field from input. Note that builders and mutable + * messages may use different Java types to represent a primtive field. + */ + Object readPrimitiveField( + CodedInputStream input, WireFormat.FieldType type, + boolean checkUtf8) throws IOException; + + /** + * Returns a new merge target for a sub-field. When defaultInstance is + * provided, it indicates the descriptor is for an extension type, and + * implementations should create a new instance from the defaultInstance + * prototype directly. + */ + MergeTarget newMergeTargetForField( + Descriptors.FieldDescriptor descriptor, + Message defaultInstance); + + /** + * Finishes the merge and returns the underlying object. + */ + Object finish(); + } + + static class BuilderAdapter implements MergeTarget { + + private final Message.Builder builder; + + public Descriptors.Descriptor getDescriptorForType() { + return builder.getDescriptorForType(); + } + + public BuilderAdapter(Message.Builder builder) { + this.builder = builder; + } + + public Object getField(Descriptors.FieldDescriptor field) { + return builder.getField(field); + } + + @Override + public boolean hasField(Descriptors.FieldDescriptor field) { + return builder.hasField(field); + } + + public MergeTarget setField(Descriptors.FieldDescriptor field, + Object value) { + builder.setField(field, value); + return this; + } + + public MergeTarget clearField(Descriptors.FieldDescriptor field) { + builder.clearField(field); + return this; + } + + public MergeTarget setRepeatedField( + Descriptors.FieldDescriptor field, int index, Object value) { + builder.setRepeatedField(field, index, value); + return this; + } + + public MergeTarget addRepeatedField( + Descriptors.FieldDescriptor field, Object value) { + builder.addRepeatedField(field, value); + return this; + } + + @Override + public boolean hasOneof(Descriptors.OneofDescriptor oneof) { + return builder.hasOneof(oneof); + } + + @Override + public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) { + builder.clearOneof(oneof); + return this; + } + + @Override + public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) { + return builder.getOneofFieldDescriptor(oneof); + } + + public ContainerType getContainerType() { + return ContainerType.MESSAGE; + } + + public ExtensionRegistry.ExtensionInfo findExtensionByName( + ExtensionRegistry registry, String name) { + return registry.findImmutableExtensionByName(name); + } + + public ExtensionRegistry.ExtensionInfo findExtensionByNumber( + ExtensionRegistry registry, Descriptors.Descriptor containingType, + int fieldNumber) { + return registry.findImmutableExtensionByNumber(containingType, + fieldNumber); + } + + public Object parseGroup(CodedInputStream input, + ExtensionRegistryLite extensionRegistry, + Descriptors.FieldDescriptor field, Message defaultInstance) + throws IOException { + Message.Builder subBuilder; + // When default instance is not null. The field is an extension field. + if (defaultInstance != null) { + subBuilder = defaultInstance.newBuilderForType(); + } else { + subBuilder = builder.newBuilderForField(field); + } + if (!field.isRepeated()) { + Message originalMessage = (Message) getField(field); + if (originalMessage != null) { + subBuilder.mergeFrom(originalMessage); + } + } + input.readGroup(field.getNumber(), subBuilder, extensionRegistry); + return subBuilder.buildPartial(); + } + + public Object parseMessage(CodedInputStream input, + ExtensionRegistryLite extensionRegistry, + Descriptors.FieldDescriptor field, Message defaultInstance) + throws IOException { + Message.Builder subBuilder; + // When default instance is not null. The field is an extension field. + if (defaultInstance != null) { + subBuilder = defaultInstance.newBuilderForType(); + } else { + subBuilder = builder.newBuilderForField(field); + } + if (!field.isRepeated()) { + Message originalMessage = (Message) getField(field); + if (originalMessage != null) { + subBuilder.mergeFrom(originalMessage); + } + } + input.readMessage(subBuilder, extensionRegistry); + return subBuilder.buildPartial(); + } + + public Object parseMessageFromBytes(ByteString bytes, + ExtensionRegistryLite extensionRegistry, + Descriptors.FieldDescriptor field, Message defaultInstance) + throws IOException { + Message.Builder subBuilder; + // When default instance is not null. The field is an extension field. + if (defaultInstance != null) { + subBuilder = defaultInstance.newBuilderForType(); + } else { + subBuilder = builder.newBuilderForField(field); + } + if (!field.isRepeated()) { + Message originalMessage = (Message) getField(field); + if (originalMessage != null) { + subBuilder.mergeFrom(originalMessage); + } + } + subBuilder.mergeFrom(bytes, extensionRegistry); + return subBuilder.buildPartial(); + } + + public MergeTarget newMergeTargetForField(Descriptors.FieldDescriptor field, + Message defaultInstance) { + if (defaultInstance != null) { + return new BuilderAdapter( + defaultInstance.newBuilderForType()); + } else { + return new BuilderAdapter(builder.newBuilderForField(field)); + } + } + + public Object readPrimitiveField( + CodedInputStream input, WireFormat.FieldType type, + boolean checkUtf8) throws IOException { + return FieldSet.readPrimitiveField(input, type, checkUtf8); + } + + public Object finish() { + return builder.buildPartial(); + } + } + + + static class ExtensionAdapter implements MergeTarget { + + private final FieldSet extensions; + + ExtensionAdapter(FieldSet extensions) { + this.extensions = extensions; + } + + public Descriptors.Descriptor getDescriptorForType() { + throw new UnsupportedOperationException( + "getDescriptorForType() called on FieldSet object"); + } + + public Object getField(Descriptors.FieldDescriptor field) { + return extensions.getField(field); + } + + public boolean hasField(Descriptors.FieldDescriptor field) { + return extensions.hasField(field); + } + + public MergeTarget setField(Descriptors.FieldDescriptor field, + Object value) { + extensions.setField(field, value); + return this; + } + + public MergeTarget clearField(Descriptors.FieldDescriptor field) { + extensions.clearField(field); + return this; + } + + public MergeTarget setRepeatedField( + Descriptors.FieldDescriptor field, int index, Object value) { + extensions.setRepeatedField(field, index, value); + return this; + } + + public MergeTarget addRepeatedField( + Descriptors.FieldDescriptor field, Object value) { + extensions.addRepeatedField(field, value); + return this; + } + + @Override + public boolean hasOneof(Descriptors.OneofDescriptor oneof) { + return false; + } + + @Override + public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) { + // Nothing to clear. + return this; + } + + @Override + public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) { + return null; + } + + public ContainerType getContainerType() { + return ContainerType.EXTENSION_SET; + } + + public ExtensionRegistry.ExtensionInfo findExtensionByName( + ExtensionRegistry registry, String name) { + return registry.findImmutableExtensionByName(name); + } + + public ExtensionRegistry.ExtensionInfo findExtensionByNumber( + ExtensionRegistry registry, Descriptors.Descriptor containingType, + int fieldNumber) { + return registry.findImmutableExtensionByNumber(containingType, + fieldNumber); + } + + public Object parseGroup(CodedInputStream input, + ExtensionRegistryLite registry, Descriptors.FieldDescriptor field, + Message defaultInstance) throws IOException { + Message.Builder subBuilder = + defaultInstance.newBuilderForType(); + if (!field.isRepeated()) { + Message originalMessage = (Message) getField(field); + if (originalMessage != null) { + subBuilder.mergeFrom(originalMessage); + } + } + input.readGroup(field.getNumber(), subBuilder, registry); + return subBuilder.buildPartial(); + } + + public Object parseMessage(CodedInputStream input, + ExtensionRegistryLite registry, Descriptors.FieldDescriptor field, + Message defaultInstance) throws IOException { + Message.Builder subBuilder = + defaultInstance.newBuilderForType(); + if (!field.isRepeated()) { + Message originalMessage = (Message) getField(field); + if (originalMessage != null) { + subBuilder.mergeFrom(originalMessage); + } + } + input.readMessage(subBuilder, registry); + return subBuilder.buildPartial(); + } + + public Object parseMessageFromBytes(ByteString bytes, + ExtensionRegistryLite registry, Descriptors.FieldDescriptor field, + Message defaultInstance) throws IOException { + Message.Builder subBuilder = defaultInstance.newBuilderForType(); + if (!field.isRepeated()) { + Message originalMessage = (Message) getField(field); + if (originalMessage != null) { + subBuilder.mergeFrom(originalMessage); + } + } + subBuilder.mergeFrom(bytes, registry); + return subBuilder.buildPartial(); + } + + public MergeTarget newMergeTargetForField( + Descriptors.FieldDescriptor descriptor, Message defaultInstance) { + throw new UnsupportedOperationException( + "newMergeTargetForField() called on FieldSet object"); + } + + public Object readPrimitiveField( + CodedInputStream input, WireFormat.FieldType type, + boolean checkUtf8) throws IOException { + return FieldSet.readPrimitiveField(input, type, checkUtf8); + } + + public Object finish() { + throw new UnsupportedOperationException( + "finish() called on FieldSet object"); + } + } + + /** + * Parses a single field into MergeTarget. The target can be Message.Builder, + * FieldSet or MutableMessage. + * + * Package-private because it is used by GeneratedMessage.ExtendableMessage. + * + * @param tag The tag, which should have already been read. + * @return {@code true} unless the tag is an end-group tag. + */ + static boolean mergeFieldFrom( + CodedInputStream input, + UnknownFieldSet.Builder unknownFields, + ExtensionRegistryLite extensionRegistry, + Descriptors.Descriptor type, + MergeTarget target, + int tag) throws IOException { + if (type.getOptions().getMessageSetWireFormat() && + tag == WireFormat.MESSAGE_SET_ITEM_TAG) { + mergeMessageSetExtensionFromCodedStream( + input, unknownFields, extensionRegistry, type, target); + return true; + } + + final int wireType = WireFormat.getTagWireType(tag); + final int fieldNumber = WireFormat.getTagFieldNumber(tag); + + final Descriptors.FieldDescriptor field; + Message defaultInstance = null; + + if (type.isExtensionNumber(fieldNumber)) { + // extensionRegistry may be either ExtensionRegistry or + // ExtensionRegistryLite. Since the type we are parsing is a full + // message, only a full ExtensionRegistry could possibly contain + // extensions of it. Otherwise we will treat the registry as if it + // were empty. + if (extensionRegistry instanceof ExtensionRegistry) { + final ExtensionRegistry.ExtensionInfo extension = + target.findExtensionByNumber((ExtensionRegistry) extensionRegistry, + type, fieldNumber); + if (extension == null) { + field = null; + } else { + field = extension.descriptor; + defaultInstance = extension.defaultInstance; + if (defaultInstance == null && + field.getJavaType() + == Descriptors.FieldDescriptor.JavaType.MESSAGE) { + throw new IllegalStateException( + "Message-typed extension lacked default instance: " + + field.getFullName()); + } + } + } else { + field = null; + } + } else if (target.getContainerType() == MergeTarget.ContainerType.MESSAGE) { + field = type.findFieldByNumber(fieldNumber); + } else { + field = null; + } + + boolean unknown = false; + boolean packed = false; + if (field == null) { + unknown = true; // Unknown field. + } else if (wireType == FieldSet.getWireFormatForFieldType( + field.getLiteType(), + false /* isPacked */)) { + packed = false; + } else if (field.isPackable() && + wireType == FieldSet.getWireFormatForFieldType( + field.getLiteType(), + true /* isPacked */)) { + packed = true; + } else { + unknown = true; // Unknown wire type. + } + + if (unknown) { // Unknown field or wrong wire type. Skip. + return unknownFields.mergeFieldFrom(tag, input); + } + + if (packed) { + final int length = input.readRawVarint32(); + final int limit = input.pushLimit(length); + if (field.getLiteType() == WireFormat.FieldType.ENUM) { + while (input.getBytesUntilLimit() > 0) { + final int rawValue = input.readEnum(); + final Object value = field.getEnumType().findValueByNumber(rawValue); + if (value == null) { + // If the number isn't recognized as a valid value for this + // enum, drop it (don't even add it to unknownFields). + return true; + } + target.addRepeatedField(field, value); + } + } else { + while (input.getBytesUntilLimit() > 0) { + final Object value = + target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check()); + target.addRepeatedField(field, value); + } + } + input.popLimit(limit); + } else { + final Object value; + switch (field.getType()) { + case GROUP: { + value = target + .parseGroup(input, extensionRegistry, field, defaultInstance); + break; + } + case MESSAGE: { + value = target + .parseMessage(input, extensionRegistry, field, defaultInstance); + break; + } + case ENUM: + final int rawValue = input.readEnum(); + value = field.getEnumType().findValueByNumber(rawValue); + // If the number isn't recognized as a valid value for this enum, + // drop it. + if (value == null) { + unknownFields.mergeVarintField(fieldNumber, rawValue); + return true; + } + break; + default: + value = target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check()); + break; + } + + if (field.isRepeated()) { + target.addRepeatedField(field, value); + } else { + target.setField(field, value); + } + } + + return true; + } + + /** + * Called by {@code #mergeFieldFrom()} to parse a MessageSet extension into + * MergeTarget. + */ + private static void mergeMessageSetExtensionFromCodedStream( + CodedInputStream input, + UnknownFieldSet.Builder unknownFields, + ExtensionRegistryLite extensionRegistry, + Descriptors.Descriptor type, + MergeTarget target) throws IOException { + + // The wire format for MessageSet is: + // message MessageSet { + // repeated group Item = 1 { + // required int32 typeId = 2; + // required bytes message = 3; + // } + // } + // "typeId" is the extension's field number. The extension can only be + // a message type, where "message" contains the encoded bytes of that + // message. + // + // In practice, we will probably never see a MessageSet item in which + // the message appears before the type ID, or where either field does not + // appear exactly once. However, in theory such cases are valid, so we + // should be prepared to accept them. + + int typeId = 0; + ByteString rawBytes = null; // If we encounter "message" before "typeId" + ExtensionRegistry.ExtensionInfo extension = null; + + // Read bytes from input, if we get it's type first then parse it eagerly, + // otherwise we store the raw bytes in a local variable. + while (true) { + final int tag = input.readTag(); + if (tag == 0) { + break; + } + + if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) { + typeId = input.readUInt32(); + if (typeId != 0) { + // extensionRegistry may be either ExtensionRegistry or + // ExtensionRegistryLite. Since the type we are parsing is a full + // message, only a full ExtensionRegistry could possibly contain + // extensions of it. Otherwise we will treat the registry as if it + // were empty. + if (extensionRegistry instanceof ExtensionRegistry) { + extension = target.findExtensionByNumber( + (ExtensionRegistry) extensionRegistry, type, typeId); + } + } + + } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) { + if (typeId != 0) { + if (extension != null && + ExtensionRegistryLite.isEagerlyParseMessageSets()) { + // We already know the type, so we can parse directly from the + // input with no copying. Hooray! + eagerlyMergeMessageSetExtension( + input, extension, extensionRegistry, target); + rawBytes = null; + continue; + } + } + // We haven't seen a type ID yet or we want parse message lazily. + rawBytes = input.readBytes(); + + } else { // Unknown tag. Skip it. + if (!input.skipField(tag)) { + break; // End of group + } + } + } + input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG); + + // Process the raw bytes. + if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID. + if (extension != null) { // We known the type + mergeMessageSetExtensionFromBytes( + rawBytes, extension, extensionRegistry, target); + } else { // We don't know how to parse this. Ignore it. + if (rawBytes != null) { + unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder() + .addLengthDelimited(rawBytes).build()); + } + } + } + } + + private static void mergeMessageSetExtensionFromBytes( + ByteString rawBytes, + ExtensionRegistry.ExtensionInfo extension, + ExtensionRegistryLite extensionRegistry, + MergeTarget target) throws IOException { + + Descriptors.FieldDescriptor field = extension.descriptor; + boolean hasOriginalValue = target.hasField(field); + + if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) { + // If the field already exists, we just parse the field. + Object value = target.parseMessageFromBytes( + rawBytes, extensionRegistry,field, extension.defaultInstance); + target.setField(field, value); + } else { + // Use LazyField to load MessageSet lazily. + LazyField lazyField = new LazyField( + extension.defaultInstance, extensionRegistry, rawBytes); + target.setField(field, lazyField); + } + } + + private static void eagerlyMergeMessageSetExtension( + CodedInputStream input, + ExtensionRegistry.ExtensionInfo extension, + ExtensionRegistryLite extensionRegistry, + MergeTarget target) throws IOException { + Descriptors.FieldDescriptor field = extension.descriptor; + Object value = target.parseMessage(input, extensionRegistry, field, + extension.defaultInstance); + target.setField(field, value); + } +} diff --git a/java/src/main/java/com/google/protobuf/Parser.java b/java/src/main/java/com/google/protobuf/Parser.java new file mode 100644 index 0000000..5fe969b --- /dev/null +++ b/java/src/main/java/com/google/protobuf/Parser.java @@ -0,0 +1,261 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.io.InputStream; + +/** + * Abstract interface for parsing Protocol Messages. + * + * The implementation should be stateless and thread-safe. + * + * @author liujisi@google.com (Pherl Liu) + */ +public interface Parser { + /** + * Parses a message of {@code MessageType} from the input. + * + *

Note: The caller should call + * {@link CodedInputStream#checkLastTagWas(int)} after calling this to + * verify that the last tag seen was the appropriate end-group tag, + * or zero for EOF. + */ + public MessageType parseFrom(CodedInputStream input) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseFrom(CodedInputStream)}, but also parses extensions. + * The extensions that you want to be able to parse must be registered in + * {@code extensionRegistry}. Extensions not in the registry will be treated + * as unknown fields. + */ + public MessageType parseFrom(CodedInputStream input, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseFrom(CodedInputStream)}, but does not throw an + * exception if the message is missing required fields. Instead, a partial + * message is returned. + */ + public MessageType parsePartialFrom(CodedInputStream input) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseFrom(CodedInputStream input, ExtensionRegistryLite)}, + * but does not throw an exception if the message is missing required fields. + * Instead, a partial message is returned. + */ + public MessageType parsePartialFrom(CodedInputStream input, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + // --------------------------------------------------------------- + // Convenience methods. + + /** + * Parses {@code data} as a message of {@code MessageType}. + * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}. + */ + public MessageType parseFrom(ByteString data) + throws InvalidProtocolBufferException; + + /** + * Parses {@code data} as a message of {@code MessageType}. + * This is just a small wrapper around + * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}. + */ + public MessageType parseFrom(ByteString data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseFrom(ByteString)}, but does not throw an + * exception if the message is missing required fields. Instead, a partial + * message is returned. + */ + public MessageType parsePartialFrom(ByteString data) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)}, + * but does not throw an exception if the message is missing required fields. + * Instead, a partial message is returned. + */ + public MessageType parsePartialFrom(ByteString data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Parses {@code data} as a message of {@code MessageType}. + * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}. + */ + public MessageType parseFrom(byte[] data, int off, int len) + throws InvalidProtocolBufferException; + + /** + * Parses {@code data} as a message of {@code MessageType}. + * This is just a small wrapper around + * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}. + */ + public MessageType parseFrom(byte[] data, int off, int len, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Parses {@code data} as a message of {@code MessageType}. + * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}. + */ + public MessageType parseFrom(byte[] data) + throws InvalidProtocolBufferException; + + /** + * Parses {@code data} as a message of {@code MessageType}. + * This is just a small wrapper around + * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}. + */ + public MessageType parseFrom(byte[] data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseFrom(byte[], int, int)}, but does not throw an + * exception if the message is missing required fields. Instead, a partial + * message is returned. + */ + public MessageType parsePartialFrom(byte[] data, int off, int len) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)}, + * but does not throw an exception if the message is missing required fields. + * Instead, a partial message is returned. + */ + public MessageType parsePartialFrom(byte[] data, int off, int len, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseFrom(byte[])}, but does not throw an + * exception if the message is missing required fields. Instead, a partial + * message is returned. + */ + public MessageType parsePartialFrom(byte[] data) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseFrom(byte[], ExtensionRegistryLite)}, + * but does not throw an exception if the message is missing required fields. + * Instead, a partial message is returned. + */ + public MessageType parsePartialFrom(byte[] data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Parse a message of {@code MessageType} from {@code input}. + * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}. + * Note that this method always reads the entire input (unless it + * throws an exception). If you want it to stop earlier, you will need to + * wrap your input in some wrapper stream that limits reading. Or, use + * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write your + * message and {@link #parseDelimitedFrom(InputStream)} to read it. + *

+ * Despite usually reading the entire input, this does not close the stream. + */ + public MessageType parseFrom(InputStream input) + throws InvalidProtocolBufferException; + + /** + * Parses a message of {@code MessageType} from {@code input}. + * This is just a small wrapper around + * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}. + */ + public MessageType parseFrom(InputStream input, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseFrom(InputStream)}, but does not throw an + * exception if the message is missing required fields. Instead, a partial + * message is returned. + */ + public MessageType parsePartialFrom(InputStream input) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseFrom(InputStream, ExtensionRegistryLite)}, + * but does not throw an exception if the message is missing required fields. + * Instead, a partial message is returned. + */ + public MessageType parsePartialFrom(InputStream input, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseFrom(InputStream)}, but does not read util EOF. + * Instead, the size of message (encoded as a varint) is read first, + * then the message data. Use + * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write + * messages in this format. + * + * @return True if successful, or false if the stream is at EOF when the + * method starts. Any other error (including reaching EOF during + * parsing) will cause an exception to be thrown. + */ + public MessageType parseDelimitedFrom(InputStream input) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseDelimitedFrom(InputStream)} but supporting extensions. + */ + public MessageType parseDelimitedFrom(InputStream input, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseDelimitedFrom(InputStream)}, but does not throw an + * exception if the message is missing required fields. Instead, a partial + * message is returned. + */ + public MessageType parsePartialDelimitedFrom(InputStream input) + throws InvalidProtocolBufferException; + + /** + * Like {@link #parseDelimitedFrom(InputStream, ExtensionRegistryLite)}, + * but does not throw an exception if the message is missing required fields. + * Instead, a partial message is returned. + */ + public MessageType parsePartialDelimitedFrom( + InputStream input, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; +} diff --git a/java/src/main/java/com/google/protobuf/ProtocolStringList.java b/java/src/main/java/com/google/protobuf/ProtocolStringList.java new file mode 100644 index 0000000..41a1f90 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/ProtocolStringList.java @@ -0,0 +1,48 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.util.List; + +/** + * An interface extending {@code List} used for repeated string fields + * to provide optional access to the data as a list of ByteStrings. The + * underlying implementation stores values as either ByteStrings or Strings + * (see {@link LazyStringArrayList}) depending on how the value was initialized + * or last read, and it is often more efficient to deal with lists of + * ByteStrings when handling protos that have been deserialized from bytes. + */ +public interface ProtocolStringList extends List { + + /** Returns a view of the data as a list of ByteStrings. */ + List asByteStringList(); + +} diff --git a/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java new file mode 100644 index 0000000..65d9270 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java @@ -0,0 +1,696 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * {@code RepeatedFieldBuilder} implements a structure that a protocol + * message uses to hold a repeated field of other protocol messages. It supports + * the classical use case of adding immutable {@link Message}'s to the + * repeated field and is highly optimized around this (no extra memory + * allocations and sharing of immutable arrays). + *
+ * It also supports the additional use case of adding a {@link Message.Builder} + * to the repeated field and deferring conversion of that {@code Builder} + * to an immutable {@code Message}. In this way, it's possible to maintain + * a tree of {@code Builder}'s that acts as a fully read/write data + * structure. + *
+ * Logically, one can think of a tree of builders as converting the entire tree + * to messages when build is called on the root or when any method is called + * that desires a Message instead of a Builder. In terms of the implementation, + * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder} + * classes cache messages that were created so that messages only need to be + * created when some change occured in its builder or a builder for one of its + * descendants. + * + * @param the type of message for the field + * @param the type of builder for the field + * @param the common interface for the message and the builder + * + * @author jonp@google.com (Jon Perlow) + */ +public class RepeatedFieldBuilder + + implements GeneratedMessage.BuilderParent { + + // Parent to send changes to. + private GeneratedMessage.BuilderParent parent; + + // List of messages. Never null. It may be immutable, in which case + // isMessagesListImmutable will be true. See note below. + private List messages; + + // Whether messages is an mutable array that can be modified. + private boolean isMessagesListMutable; + + // List of builders. May be null, in which case, no nested builders were + // created. If not null, entries represent the builder for that index. + private List> builders; + + // Here are the invariants for messages and builders: + // 1. messages is never null and its count corresponds to the number of items + // in the repeated field. + // 2. If builders is non-null, messages and builders MUST always + // contain the same number of items. + // 3. Entries in either array can be null, but for any index, there MUST be + // either a Message in messages or a builder in builders. + // 4. If the builder at an index is non-null, the builder is + // authoritative. This is the case where a Builder was set on the index. + // Any message in the messages array MUST be ignored. + // t. If the builder at an index is null, the message in the messages + // list is authoritative. This is the case where a Message (not a Builder) + // was set directly for an index. + + // Indicates that we've built a message and so we are now obligated + // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener. + private boolean isClean; + + // A view of this builder that exposes a List interface of messages. This is + // initialized on demand. This is fully backed by this object and all changes + // are reflected in it. Access to any item converts it to a message if it + // was a builder. + private MessageExternalList externalMessageList; + + // A view of this builder that exposes a List interface of builders. This is + // initialized on demand. This is fully backed by this object and all changes + // are reflected in it. Access to any item converts it to a builder if it + // was a message. + private BuilderExternalList externalBuilderList; + + // A view of this builder that exposes a List interface of the interface + // implemented by messages and builders. This is initialized on demand. This + // is fully backed by this object and all changes are reflected in it. + // Access to any item returns either a builder or message depending on + // what is most efficient. + private MessageOrBuilderExternalList + externalMessageOrBuilderList; + + /** + * Constructs a new builder with an empty list of messages. + * + * @param messages the current list of messages + * @param isMessagesListMutable Whether the messages list is mutable + * @param parent a listener to notify of changes + * @param isClean whether the builder is initially marked clean + */ + public RepeatedFieldBuilder( + List messages, + boolean isMessagesListMutable, + GeneratedMessage.BuilderParent parent, + boolean isClean) { + this.messages = messages; + this.isMessagesListMutable = isMessagesListMutable; + this.parent = parent; + this.isClean = isClean; + } + + public void dispose() { + // Null out parent so we stop sending it invalidations. + parent = null; + } + + /** + * Ensures that the list of messages is mutable so it can be updated. If it's + * immutable, a copy is made. + */ + private void ensureMutableMessageList() { + if (!isMessagesListMutable) { + messages = new ArrayList(messages); + isMessagesListMutable = true; + } + } + + /** + * Ensures that the list of builders is not null. If it's null, the list is + * created and initialized to be the same size as the messages list with + * null entries. + */ + private void ensureBuilders() { + if (this.builders == null) { + this.builders = + new ArrayList>( + messages.size()); + for (int i = 0; i < messages.size(); i++) { + builders.add(null); + } + } + } + + /** + * Gets the count of items in the list. + * + * @return the count of items in the list. + */ + public int getCount() { + return messages.size(); + } + + /** + * Gets whether the list is empty. + * + * @return whether the list is empty + */ + public boolean isEmpty() { + return messages.isEmpty(); + } + + /** + * Get the message at the specified index. If the message is currently stored + * as a {@code Builder}, it is converted to a {@code Message} by + * calling {@link Message.Builder#buildPartial} on it. + * + * @param index the index of the message to get + * @return the message for the specified index + */ + public MType getMessage(int index) { + return getMessage(index, false); + } + + /** + * Get the message at the specified index. If the message is currently stored + * as a {@code Builder}, it is converted to a {@code Message} by + * calling {@link Message.Builder#buildPartial} on it. + * + * @param index the index of the message to get + * @param forBuild this is being called for build so we want to make sure + * we SingleFieldBuilder.build to send dirty invalidations + * @return the message for the specified index + */ + private MType getMessage(int index, boolean forBuild) { + if (this.builders == null) { + // We don't have any builders -- return the current Message. + // This is the case where no builder was created, so we MUST have a + // Message. + return messages.get(index); + } + + SingleFieldBuilder builder = builders.get(index); + if (builder == null) { + // We don't have a builder -- return the current message. + // This is the case where no builder was created for the entry at index, + // so we MUST have a message. + return messages.get(index); + + } else { + return forBuild ? builder.build() : builder.getMessage(); + } + } + + /** + * Gets a builder for the specified index. If no builder has been created for + * that index, a builder is created on demand by calling + * {@link Message#toBuilder}. + * + * @param index the index of the message to get + * @return The builder for that index + */ + public BType getBuilder(int index) { + ensureBuilders(); + SingleFieldBuilder builder = builders.get(index); + if (builder == null) { + MType message = messages.get(index); + builder = new SingleFieldBuilder( + message, this, isClean); + builders.set(index, builder); + } + return builder.getBuilder(); + } + + /** + * Gets the base class interface for the specified index. This may either be + * a builder or a message. It will return whatever is more efficient. + * + * @param index the index of the message to get + * @return the message or builder for the index as the base class interface + */ + @SuppressWarnings("unchecked") + public IType getMessageOrBuilder(int index) { + if (this.builders == null) { + // We don't have any builders -- return the current Message. + // This is the case where no builder was created, so we MUST have a + // Message. + return (IType) messages.get(index); + } + + SingleFieldBuilder builder = builders.get(index); + if (builder == null) { + // We don't have a builder -- return the current message. + // This is the case where no builder was created for the entry at index, + // so we MUST have a message. + return (IType) messages.get(index); + + } else { + return builder.getMessageOrBuilder(); + } + } + + /** + * Sets a message at the specified index replacing the existing item at + * that index. + * + * @param index the index to set. + * @param message the message to set + * @return the builder + */ + public RepeatedFieldBuilder setMessage( + int index, MType message) { + if (message == null) { + throw new NullPointerException(); + } + ensureMutableMessageList(); + messages.set(index, message); + if (builders != null) { + SingleFieldBuilder entry = + builders.set(index, null); + if (entry != null) { + entry.dispose(); + } + } + onChanged(); + incrementModCounts(); + return this; + } + + /** + * Appends the specified element to the end of this list. + * + * @param message the message to add + * @return the builder + */ + public RepeatedFieldBuilder addMessage( + MType message) { + if (message == null) { + throw new NullPointerException(); + } + ensureMutableMessageList(); + messages.add(message); + if (builders != null) { + builders.add(null); + } + onChanged(); + incrementModCounts(); + return this; + } + + /** + * Inserts the specified message at the specified position in this list. + * Shifts the element currently at that position (if any) and any subsequent + * elements to the right (adds one to their indices). + * + * @param index the index at which to insert the message + * @param message the message to add + * @return the builder + */ + public RepeatedFieldBuilder addMessage( + int index, MType message) { + if (message == null) { + throw new NullPointerException(); + } + ensureMutableMessageList(); + messages.add(index, message); + if (builders != null) { + builders.add(index, null); + } + onChanged(); + incrementModCounts(); + return this; + } + + /** + * Appends all of the messages in the specified collection to the end of + * this list, in the order that they are returned by the specified + * collection's iterator. + * + * @param values the messages to add + * @return the builder + */ + public RepeatedFieldBuilder addAllMessages( + Iterable values) { + for (final MType value : values) { + if (value == null) { + throw new NullPointerException(); + } + } + if (values instanceof Collection) { + @SuppressWarnings("unchecked") final + Collection collection = (Collection) values; + if (collection.size() == 0) { + return this; + } + ensureMutableMessageList(); + for (MType value : values) { + addMessage(value); + } + } else { + ensureMutableMessageList(); + for (MType value : values) { + addMessage(value); + } + } + onChanged(); + incrementModCounts(); + return this; + } + + /** + * Appends a new builder to the end of this list and returns the builder. + * + * @param message the message to add which is the basis of the builder + * @return the new builder + */ + public BType addBuilder(MType message) { + ensureMutableMessageList(); + ensureBuilders(); + SingleFieldBuilder builder = + new SingleFieldBuilder( + message, this, isClean); + messages.add(null); + builders.add(builder); + onChanged(); + incrementModCounts(); + return builder.getBuilder(); + } + + /** + * Inserts a new builder at the specified position in this list. + * Shifts the element currently at that position (if any) and any subsequent + * elements to the right (adds one to their indices). + * + * @param index the index at which to insert the builder + * @param message the message to add which is the basis of the builder + * @return the builder + */ + public BType addBuilder(int index, MType message) { + ensureMutableMessageList(); + ensureBuilders(); + SingleFieldBuilder builder = + new SingleFieldBuilder( + message, this, isClean); + messages.add(index, null); + builders.add(index, builder); + onChanged(); + incrementModCounts(); + return builder.getBuilder(); + } + + /** + * Removes the element at the specified position in this list. Shifts any + * subsequent elements to the left (subtracts one from their indices). + * Returns the element that was removed from the list. + * + * @param index the index at which to remove the message + */ + public void remove(int index) { + ensureMutableMessageList(); + messages.remove(index); + if (builders != null) { + SingleFieldBuilder entry = + builders.remove(index); + if (entry != null) { + entry.dispose(); + } + } + onChanged(); + incrementModCounts(); + } + + /** + * Removes all of the elements from this list. + * The list will be empty after this call returns. + */ + public void clear() { + messages = Collections.emptyList(); + isMessagesListMutable = false; + if (builders != null) { + for (SingleFieldBuilder entry : + builders) { + if (entry != null) { + entry.dispose(); + } + } + builders = null; + } + onChanged(); + incrementModCounts(); + } + + /** + * Builds the list of messages from the builder and returns them. + * + * @return an immutable list of messages + */ + public List build() { + // Now that build has been called, we are required to dispatch + // invalidations. + isClean = true; + + if (!isMessagesListMutable && builders == null) { + // We still have an immutable list and we never created a builder. + return messages; + } + + boolean allMessagesInSync = true; + if (!isMessagesListMutable) { + // We still have an immutable list. Let's see if any of them are out + // of sync with their builders. + for (int i = 0; i < messages.size(); i++) { + Message message = messages.get(i); + SingleFieldBuilder builder = builders.get(i); + if (builder != null) { + if (builder.build() != message) { + allMessagesInSync = false; + break; + } + } + } + if (allMessagesInSync) { + // Immutable list is still in sync. + return messages; + } + } + + // Need to make sure messages is up to date + ensureMutableMessageList(); + for (int i = 0; i < messages.size(); i++) { + messages.set(i, getMessage(i, true)); + } + + // We're going to return our list as immutable so we mark that we can + // no longer update it. + messages = Collections.unmodifiableList(messages); + isMessagesListMutable = false; + return messages; + } + + /** + * Gets a view of the builder as a list of messages. The returned list is live + * and will reflect any changes to the underlying builder. + * + * @return the messages in the list + */ + public List getMessageList() { + if (externalMessageList == null) { + externalMessageList = + new MessageExternalList(this); + } + return externalMessageList; + } + + /** + * Gets a view of the builder as a list of builders. This returned list is + * live and will reflect any changes to the underlying builder. + * + * @return the builders in the list + */ + public List getBuilderList() { + if (externalBuilderList == null) { + externalBuilderList = + new BuilderExternalList(this); + } + return externalBuilderList; + } + + /** + * Gets a view of the builder as a list of MessageOrBuilders. This returned + * list is live and will reflect any changes to the underlying builder. + * + * @return the builders in the list + */ + public List getMessageOrBuilderList() { + if (externalMessageOrBuilderList == null) { + externalMessageOrBuilderList = + new MessageOrBuilderExternalList(this); + } + return externalMessageOrBuilderList; + } + + /** + * Called when a the builder or one of its nested children has changed + * and any parent should be notified of its invalidation. + */ + private void onChanged() { + if (isClean && parent != null) { + parent.markDirty(); + + // Don't keep dispatching invalidations until build is called again. + isClean = false; + } + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void markDirty() { + onChanged(); + } + + /** + * Increments the mod counts so that an ConcurrentModificationException can + * be thrown if calling code tries to modify the builder while its iterating + * the list. + */ + private void incrementModCounts() { + if (externalMessageList != null) { + externalMessageList.incrementModCount(); + } + if (externalBuilderList != null) { + externalBuilderList.incrementModCount(); + } + if (externalMessageOrBuilderList != null) { + externalMessageOrBuilderList.incrementModCount(); + } + } + + /** + * Provides a live view of the builder as a list of messages. + * + * @param the type of message for the field + * @param the type of builder for the field + * @param the common interface for the message and the builder + */ + private static class MessageExternalList< + MType extends GeneratedMessage, + BType extends GeneratedMessage.Builder, + IType extends MessageOrBuilder> + extends AbstractList implements List { + + RepeatedFieldBuilder builder; + + MessageExternalList( + RepeatedFieldBuilder builder) { + this.builder = builder; + } + + public int size() { + return this.builder.getCount(); + } + + public MType get(int index) { + return builder.getMessage(index); + } + + void incrementModCount() { + modCount++; + } + } + + /** + * Provides a live view of the builder as a list of builders. + * + * @param the type of message for the field + * @param the type of builder for the field + * @param the common interface for the message and the builder + */ + private static class BuilderExternalList< + MType extends GeneratedMessage, + BType extends GeneratedMessage.Builder, + IType extends MessageOrBuilder> + extends AbstractList implements List { + + RepeatedFieldBuilder builder; + + BuilderExternalList( + RepeatedFieldBuilder builder) { + this.builder = builder; + } + + public int size() { + return this.builder.getCount(); + } + + public BType get(int index) { + return builder.getBuilder(index); + } + + void incrementModCount() { + modCount++; + } + } + + /** + * Provides a live view of the builder as a list of builders. + * + * @param the type of message for the field + * @param the type of builder for the field + * @param the common interface for the message and the builder + */ + private static class MessageOrBuilderExternalList< + MType extends GeneratedMessage, + BType extends GeneratedMessage.Builder, + IType extends MessageOrBuilder> + extends AbstractList implements List { + + RepeatedFieldBuilder builder; + + MessageOrBuilderExternalList( + RepeatedFieldBuilder builder) { + this.builder = builder; + } + + public int size() { + return this.builder.getCount(); + } + + public IType get(int index) { + return builder.getMessageOrBuilder(index); + } + + void incrementModCount() { + modCount++; + } + } +} diff --git a/java/src/main/java/com/google/protobuf/RopeByteString.java b/java/src/main/java/com/google/protobuf/RopeByteString.java new file mode 100644 index 0000000..a011df4 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/RopeByteString.java @@ -0,0 +1,957 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.io.ByteArrayInputStream; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Stack; + +/** + * Class to represent {@code ByteStrings} formed by concatenation of other + * ByteStrings, without copying the data in the pieces. The concatenation is + * represented as a tree whose leaf nodes are each a {@link LiteralByteString}. + * + *

Most of the operation here is inspired by the now-famous paper + * BAP95 Ropes: an Alternative to Strings hans-j. boehm, russ atkinson and + * michael plass + * + *

The algorithms described in the paper have been implemented for character + * strings in {@link com.google.common.string.Rope} and in the c++ class {@code + * cord.cc}. + * + *

Fundamentally the Rope algorithm represents the collection of pieces as a + * binary tree. BAP95 uses a Fibonacci bound relating depth to a minimum + * sequence length, sequences that are too short relative to their depth cause a + * tree rebalance. More precisely, a tree of depth d is "balanced" in the + * terminology of BAP95 if its length is at least F(d+2), where F(n) is the + * n-the Fibonacci number. Thus for depths 0, 1, 2, 3, 4, 5,... we have minimum + * lengths 1, 2, 3, 5, 8, 13,... + * + * @author carlanton@google.com (Carl Haverl) + */ +class RopeByteString extends ByteString { + + /** + * BAP95. Let Fn be the nth Fibonacci number. A {@link RopeByteString} of + * depth n is "balanced", i.e flat enough, if its length is at least Fn+2, + * e.g. a "balanced" {@link RopeByteString} of depth 1 must have length at + * least 2, of depth 4 must have length >= 8, etc. + * + *

There's nothing special about using the Fibonacci numbers for this, but + * they are a reasonable sequence for encapsulating the idea that we are OK + * with longer strings being encoded in deeper binary trees. + * + *

For 32-bit integers, this array has length 46. + */ + private static final int[] minLengthByDepth; + + static { + // Dynamically generate the list of Fibonacci numbers the first time this + // class is accessed. + List numbers = new ArrayList(); + + // we skip the first Fibonacci number (1). So instead of: 1 1 2 3 5 8 ... + // we have: 1 2 3 5 8 ... + int f1 = 1; + int f2 = 1; + + // get all the values until we roll over. + while (f2 > 0) { + numbers.add(f2); + int temp = f1 + f2; + f1 = f2; + f2 = temp; + } + + // we include this here so that we can index this array to [x + 1] in the + // loops below. + numbers.add(Integer.MAX_VALUE); + minLengthByDepth = new int[numbers.size()]; + for (int i = 0; i < minLengthByDepth.length; i++) { + // unbox all the values + minLengthByDepth[i] = numbers.get(i); + } + } + + private final int totalLength; + private final ByteString left; + private final ByteString right; + private final int leftLength; + private final int treeDepth; + + /** + * Create a new RopeByteString, which can be thought of as a new tree node, by + * recording references to the two given strings. + * + * @param left string on the left of this node, should have {@code size() > + * 0} + * @param right string on the right of this node, should have {@code size() > + * 0} + */ + private RopeByteString(ByteString left, ByteString right) { + this.left = left; + this.right = right; + leftLength = left.size(); + totalLength = leftLength + right.size(); + treeDepth = Math.max(left.getTreeDepth(), right.getTreeDepth()) + 1; + } + + /** + * Concatenate the given strings while performing various optimizations to + * slow the growth rate of tree depth and tree node count. The result is + * either a {@link LiteralByteString} or a {@link RopeByteString} + * depending on which optimizations, if any, were applied. + * + *

Small pieces of length less than {@link + * ByteString#CONCATENATE_BY_COPY_SIZE} may be copied by value here, as in + * BAP95. Large pieces are referenced without copy. + * + * @param left string on the left + * @param right string on the right + * @return concatenation representing the same sequence as the given strings + */ + static ByteString concatenate(ByteString left, ByteString right) { + ByteString result; + RopeByteString leftRope = + (left instanceof RopeByteString) ? (RopeByteString) left : null; + if (right.size() == 0) { + result = left; + } else if (left.size() == 0) { + result = right; + } else { + int newLength = left.size() + right.size(); + if (newLength < ByteString.CONCATENATE_BY_COPY_SIZE) { + // Optimization from BAP95: For short (leaves in paper, but just short + // here) total length, do a copy of data to a new leaf. + result = concatenateBytes(left, right); + } else if (leftRope != null + && leftRope.right.size() + right.size() < CONCATENATE_BY_COPY_SIZE) { + // Optimization from BAP95: As an optimization of the case where the + // ByteString is constructed by repeated concatenate, recognize the case + // where a short string is concatenated to a left-hand node whose + // right-hand branch is short. In the paper this applies to leaves, but + // we just look at the length here. This has the advantage of shedding + // references to unneeded data when substrings have been taken. + // + // When we recognize this case, we do a copy of the data and create a + // new parent node so that the depth of the result is the same as the + // given left tree. + ByteString newRight = concatenateBytes(leftRope.right, right); + result = new RopeByteString(leftRope.left, newRight); + } else if (leftRope != null + && leftRope.left.getTreeDepth() > leftRope.right.getTreeDepth() + && leftRope.getTreeDepth() > right.getTreeDepth()) { + // Typically for concatenate-built strings the left-side is deeper than + // the right. This is our final attempt to concatenate without + // increasing the tree depth. We'll redo the the node on the RHS. This + // is yet another optimization for building the string by repeatedly + // concatenating on the right. + ByteString newRight = new RopeByteString(leftRope.right, right); + result = new RopeByteString(leftRope.left, newRight); + } else { + // Fine, we'll add a node and increase the tree depth--unless we + // rebalance ;^) + int newDepth = Math.max(left.getTreeDepth(), right.getTreeDepth()) + 1; + if (newLength >= minLengthByDepth[newDepth]) { + // The tree is shallow enough, so don't rebalance + result = new RopeByteString(left, right); + } else { + result = new Balancer().balance(left, right); + } + } + } + return result; + } + + /** + * Concatenates two strings by copying data values. This is called in a few + * cases in order to reduce the growth of the number of tree nodes. + * + * @param left string on the left + * @param right string on the right + * @return string formed by copying data bytes + */ + private static LiteralByteString concatenateBytes(ByteString left, + ByteString right) { + int leftSize = left.size(); + int rightSize = right.size(); + byte[] bytes = new byte[leftSize + rightSize]; + left.copyTo(bytes, 0, 0, leftSize); + right.copyTo(bytes, 0, leftSize, rightSize); + return new LiteralByteString(bytes); // Constructor wraps bytes + } + + /** + * Create a new RopeByteString for testing only while bypassing all the + * defenses of {@link #concatenate(ByteString, ByteString)}. This allows + * testing trees of specific structure. We are also able to insert empty + * leaves, though these are dis-allowed, so that we can make sure the + * implementation can withstand their presence. + * + * @param left string on the left of this node + * @param right string on the right of this node + * @return an unsafe instance for testing only + */ + static RopeByteString newInstanceForTest(ByteString left, ByteString right) { + return new RopeByteString(left, right); + } + + /** + * Gets the byte at the given index. + * Throws {@link ArrayIndexOutOfBoundsException} for backwards-compatibility + * reasons although it would more properly be {@link + * IndexOutOfBoundsException}. + * + * @param index index of byte + * @return the value + * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size + */ + @Override + public byte byteAt(int index) { + if (index < 0) { + throw new ArrayIndexOutOfBoundsException("Index < 0: " + index); + } + if (index > totalLength) { + throw new ArrayIndexOutOfBoundsException( + "Index > length: " + index + ", " + totalLength); + } + + byte result; + // Find the relevant piece by recursive descent + if (index < leftLength) { + result = left.byteAt(index); + } else { + result = right.byteAt(index - leftLength); + } + return result; + } + + @Override + public int size() { + return totalLength; + } + + // ================================================================= + // Pieces + + @Override + protected int getTreeDepth() { + return treeDepth; + } + + /** + * Determines if the tree is balanced according to BAP95, which means the tree + * is flat-enough with respect to the bounds. Note that this definition of + * balanced is one where sub-trees of balanced trees are not necessarily + * balanced. + * + * @return true if the tree is balanced + */ + @Override + protected boolean isBalanced() { + return totalLength >= minLengthByDepth[treeDepth]; + } + + /** + * Takes a substring of this one. This involves recursive descent along the + * left and right edges of the substring, and referencing any wholly contained + * segments in between. Any leaf nodes entirely uninvolved in the substring + * will not be referenced by the substring. + * + *

Substrings of {@code length < 2} should result in at most a single + * recursive call chain, terminating at a leaf node. Thus the result will be a + * {@link LiteralByteString}. {@link #RopeByteString(ByteString, + * ByteString)}. + * + * @param beginIndex start at this index + * @param endIndex the last character is the one before this index + * @return substring leaf node or tree + */ + @Override + public ByteString substring(int beginIndex, int endIndex) { + if (beginIndex < 0) { + throw new IndexOutOfBoundsException( + "Beginning index: " + beginIndex + " < 0"); + } + if (endIndex > totalLength) { + throw new IndexOutOfBoundsException( + "End index: " + endIndex + " > " + totalLength); + } + int substringLength = endIndex - beginIndex; + if (substringLength < 0) { + throw new IndexOutOfBoundsException( + "Beginning index larger than ending index: " + beginIndex + ", " + + endIndex); + } + + ByteString result; + if (substringLength == 0) { + // Empty substring + result = ByteString.EMPTY; + } else if (substringLength == totalLength) { + // The whole string + result = this; + } else { + // Proper substring + if (endIndex <= leftLength) { + // Substring on the left + result = left.substring(beginIndex, endIndex); + } else if (beginIndex >= leftLength) { + // Substring on the right + result = right + .substring(beginIndex - leftLength, endIndex - leftLength); + } else { + // Split substring + ByteString leftSub = left.substring(beginIndex); + ByteString rightSub = right.substring(0, endIndex - leftLength); + // Intentionally not rebalancing, since in many cases these two + // substrings will already be less deep than the top-level + // RopeByteString we're taking a substring of. + result = new RopeByteString(leftSub, rightSub); + } + } + return result; + } + + // ================================================================= + // ByteString -> byte[] + + @Override + protected void copyToInternal(byte[] target, int sourceOffset, + int targetOffset, int numberToCopy) { + if (sourceOffset + numberToCopy <= leftLength) { + left.copyToInternal(target, sourceOffset, targetOffset, numberToCopy); + } else if (sourceOffset >= leftLength) { + right.copyToInternal(target, sourceOffset - leftLength, targetOffset, + numberToCopy); + } else { + int leftLength = this.leftLength - sourceOffset; + left.copyToInternal(target, sourceOffset, targetOffset, leftLength); + right.copyToInternal(target, 0, targetOffset + leftLength, + numberToCopy - leftLength); + } + } + + @Override + public void copyTo(ByteBuffer target) { + left.copyTo(target); + right.copyTo(target); + } + + @Override + public ByteBuffer asReadOnlyByteBuffer() { + ByteBuffer byteBuffer = ByteBuffer.wrap(toByteArray()); + return byteBuffer.asReadOnlyBuffer(); + } + + @Override + public List asReadOnlyByteBufferList() { + // Walk through the list of LiteralByteString's that make up this + // rope, and add each one as a read-only ByteBuffer. + List result = new ArrayList(); + PieceIterator pieces = new PieceIterator(this); + while (pieces.hasNext()) { + LiteralByteString byteString = pieces.next(); + result.add(byteString.asReadOnlyByteBuffer()); + } + return result; + } + + @Override + public void writeTo(OutputStream outputStream) throws IOException { + left.writeTo(outputStream); + right.writeTo(outputStream); + } + + @Override + void writeToInternal(OutputStream out, int sourceOffset, + int numberToWrite) throws IOException { + if (sourceOffset + numberToWrite <= leftLength) { + left.writeToInternal(out, sourceOffset, numberToWrite); + } else if (sourceOffset >= leftLength) { + right.writeToInternal(out, sourceOffset - leftLength, numberToWrite); + } else { + int numberToWriteInLeft = leftLength - sourceOffset; + left.writeToInternal(out, sourceOffset, numberToWriteInLeft); + right.writeToInternal(out, 0, numberToWrite - numberToWriteInLeft); + } + } + + @Override + public String toString(String charsetName) + throws UnsupportedEncodingException { + return new String(toByteArray(), charsetName); + } + + // ================================================================= + // UTF-8 decoding + + @Override + public boolean isValidUtf8() { + int leftPartial = left.partialIsValidUtf8(Utf8.COMPLETE, 0, leftLength); + int state = right.partialIsValidUtf8(leftPartial, 0, right.size()); + return state == Utf8.COMPLETE; + } + + @Override + protected int partialIsValidUtf8(int state, int offset, int length) { + int toIndex = offset + length; + if (toIndex <= leftLength) { + return left.partialIsValidUtf8(state, offset, length); + } else if (offset >= leftLength) { + return right.partialIsValidUtf8(state, offset - leftLength, length); + } else { + int leftLength = this.leftLength - offset; + int leftPartial = left.partialIsValidUtf8(state, offset, leftLength); + return right.partialIsValidUtf8(leftPartial, 0, length - leftLength); + } + } + + // ================================================================= + // equals() and hashCode() + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if (!(other instanceof ByteString)) { + return false; + } + + ByteString otherByteString = (ByteString) other; + if (totalLength != otherByteString.size()) { + return false; + } + if (totalLength == 0) { + return true; + } + + // You don't really want to be calling equals on long strings, but since + // we cache the hashCode, we effectively cache inequality. We use the cached + // hashCode if it's already computed. It's arguable we should compute the + // hashCode here, and if we're going to be testing a bunch of byteStrings, + // it might even make sense. + if (hash != 0) { + int cachedOtherHash = otherByteString.peekCachedHashCode(); + if (cachedOtherHash != 0 && hash != cachedOtherHash) { + return false; + } + } + + return equalsFragments(otherByteString); + } + + /** + * Determines if this string is equal to another of the same length by + * iterating over the leaf nodes. On each step of the iteration, the + * overlapping segments of the leaves are compared. + * + * @param other string of the same length as this one + * @return true if the values of this string equals the value of the given + * one + */ + private boolean equalsFragments(ByteString other) { + int thisOffset = 0; + Iterator thisIter = new PieceIterator(this); + LiteralByteString thisString = thisIter.next(); + + int thatOffset = 0; + Iterator thatIter = new PieceIterator(other); + LiteralByteString thatString = thatIter.next(); + + int pos = 0; + while (true) { + int thisRemaining = thisString.size() - thisOffset; + int thatRemaining = thatString.size() - thatOffset; + int bytesToCompare = Math.min(thisRemaining, thatRemaining); + + // At least one of the offsets will be zero + boolean stillEqual = (thisOffset == 0) + ? thisString.equalsRange(thatString, thatOffset, bytesToCompare) + : thatString.equalsRange(thisString, thisOffset, bytesToCompare); + if (!stillEqual) { + return false; + } + + pos += bytesToCompare; + if (pos >= totalLength) { + if (pos == totalLength) { + return true; + } + throw new IllegalStateException(); + } + // We always get to the end of at least one of the pieces + if (bytesToCompare == thisRemaining) { // If reached end of this + thisOffset = 0; + thisString = thisIter.next(); + } else { + thisOffset += bytesToCompare; + } + if (bytesToCompare == thatRemaining) { // If reached end of that + thatOffset = 0; + thatString = thatIter.next(); + } else { + thatOffset += bytesToCompare; + } + } + } + + /** + * Cached hash value. Intentionally accessed via a data race, which is safe + * because of the Java Memory Model's "no out-of-thin-air values" guarantees + * for ints. + */ + private int hash = 0; + + @Override + public int hashCode() { + int h = hash; + + if (h == 0) { + h = totalLength; + h = partialHash(h, 0, totalLength); + if (h == 0) { + h = 1; + } + hash = h; + } + return h; + } + + @Override + protected int peekCachedHashCode() { + return hash; + } + + @Override + protected int partialHash(int h, int offset, int length) { + int toIndex = offset + length; + if (toIndex <= leftLength) { + return left.partialHash(h, offset, length); + } else if (offset >= leftLength) { + return right.partialHash(h, offset - leftLength, length); + } else { + int leftLength = this.leftLength - offset; + int leftPartial = left.partialHash(h, offset, leftLength); + return right.partialHash(leftPartial, 0, length - leftLength); + } + } + + // ================================================================= + // Input stream + + @Override + public CodedInputStream newCodedInput() { + return CodedInputStream.newInstance(new RopeInputStream()); + } + + @Override + public InputStream newInput() { + return new RopeInputStream(); + } + + /** + * This class implements the balancing algorithm of BAP95. In the paper the + * authors use an array to keep track of pieces, while here we use a stack. + * The tree is balanced by traversing subtrees in left to right order, and the + * stack always contains the part of the string we've traversed so far. + * + *

One surprising aspect of the algorithm is the result of balancing is not + * necessarily balanced, though it is nearly balanced. For details, see + * BAP95. + */ + private static class Balancer { + // Stack containing the part of the string, starting from the left, that + // we've already traversed. The final string should be the equivalent of + // concatenating the strings on the stack from bottom to top. + private final Stack prefixesStack = new Stack(); + + private ByteString balance(ByteString left, ByteString right) { + doBalance(left); + doBalance(right); + + // Sweep stack to gather the result + ByteString partialString = prefixesStack.pop(); + while (!prefixesStack.isEmpty()) { + ByteString newLeft = prefixesStack.pop(); + partialString = new RopeByteString(newLeft, partialString); + } + // We should end up with a RopeByteString since at a minimum we will + // create one from concatenating left and right + return partialString; + } + + private void doBalance(ByteString root) { + // BAP95: Insert balanced subtrees whole. This means the result might not + // be balanced, leading to repeated rebalancings on concatenate. However, + // these rebalancings are shallow due to ignoring balanced subtrees, and + // relatively few calls to insert() result. + if (root.isBalanced()) { + insert(root); + } else if (root instanceof RopeByteString) { + RopeByteString rbs = (RopeByteString) root; + doBalance(rbs.left); + doBalance(rbs.right); + } else { + throw new IllegalArgumentException( + "Has a new type of ByteString been created? Found " + + root.getClass()); + } + } + + /** + * Push a string on the balance stack (BAP95). BAP95 uses an array and + * calls the elements in the array 'bins'. We instead use a stack, so the + * 'bins' of lengths are represented by differences between the elements of + * minLengthByDepth. + * + *

If the length bin for our string, and all shorter length bins, are + * empty, we just push it on the stack. Otherwise, we need to start + * concatenating, putting the given string in the "middle" and continuing + * until we land in an empty length bin that matches the length of our + * concatenation. + * + * @param byteString string to place on the balance stack + */ + private void insert(ByteString byteString) { + int depthBin = getDepthBinForLength(byteString.size()); + int binEnd = minLengthByDepth[depthBin + 1]; + + // BAP95: Concatenate all trees occupying bins representing the length of + // our new piece or of shorter pieces, to the extent that is possible. + // The goal is to clear the bin which our piece belongs in, but that may + // not be entirely possible if there aren't enough longer bins occupied. + if (prefixesStack.isEmpty() || prefixesStack.peek().size() >= binEnd) { + prefixesStack.push(byteString); + } else { + int binStart = minLengthByDepth[depthBin]; + + // Concatenate the subtrees of shorter length + ByteString newTree = prefixesStack.pop(); + while (!prefixesStack.isEmpty() + && prefixesStack.peek().size() < binStart) { + ByteString left = prefixesStack.pop(); + newTree = new RopeByteString(left, newTree); + } + + // Concatenate the given string + newTree = new RopeByteString(newTree, byteString); + + // Continue concatenating until we land in an empty bin + while (!prefixesStack.isEmpty()) { + depthBin = getDepthBinForLength(newTree.size()); + binEnd = minLengthByDepth[depthBin + 1]; + if (prefixesStack.peek().size() < binEnd) { + ByteString left = prefixesStack.pop(); + newTree = new RopeByteString(left, newTree); + } else { + break; + } + } + prefixesStack.push(newTree); + } + } + + private int getDepthBinForLength(int length) { + int depth = Arrays.binarySearch(minLengthByDepth, length); + if (depth < 0) { + // It wasn't an exact match, so convert to the index of the containing + // fragment, which is one less even than the insertion point. + int insertionPoint = -(depth + 1); + depth = insertionPoint - 1; + } + + return depth; + } + } + + /** + * This class is a continuable tree traversal, which keeps the state + * information which would exist on the stack in a recursive traversal instead + * on a stack of "Bread Crumbs". The maximum depth of the stack in this + * iterator is the same as the depth of the tree being traversed. + * + *

This iterator is used to implement + * {@link RopeByteString#equalsFragments(ByteString)}. + */ + private static class PieceIterator implements Iterator { + + private final Stack breadCrumbs = + new Stack(); + private LiteralByteString next; + + private PieceIterator(ByteString root) { + next = getLeafByLeft(root); + } + + private LiteralByteString getLeafByLeft(ByteString root) { + ByteString pos = root; + while (pos instanceof RopeByteString) { + RopeByteString rbs = (RopeByteString) pos; + breadCrumbs.push(rbs); + pos = rbs.left; + } + return (LiteralByteString) pos; + } + + private LiteralByteString getNextNonEmptyLeaf() { + while (true) { + // Almost always, we go through this loop exactly once. However, if + // we discover an empty string in the rope, we toss it and try again. + if (breadCrumbs.isEmpty()) { + return null; + } else { + LiteralByteString result = getLeafByLeft(breadCrumbs.pop().right); + if (!result.isEmpty()) { + return result; + } + } + } + } + + public boolean hasNext() { + return next != null; + } + + /** + * Returns the next item and advances one {@code LiteralByteString}. + * + * @return next non-empty LiteralByteString or {@code null} + */ + public LiteralByteString next() { + if (next == null) { + throw new NoSuchElementException(); + } + LiteralByteString result = next; + next = getNextNonEmptyLeaf(); + return result; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } + + // ================================================================= + // ByteIterator + + @Override + public ByteIterator iterator() { + return new RopeByteIterator(); + } + + private class RopeByteIterator implements ByteString.ByteIterator { + + private final PieceIterator pieces; + private ByteIterator bytes; + int bytesRemaining; + + private RopeByteIterator() { + pieces = new PieceIterator(RopeByteString.this); + bytes = pieces.next().iterator(); + bytesRemaining = size(); + } + + public boolean hasNext() { + return (bytesRemaining > 0); + } + + public Byte next() { + return nextByte(); // Does not instantiate a Byte + } + + public byte nextByte() { + if (!bytes.hasNext()) { + bytes = pieces.next().iterator(); + } + --bytesRemaining; + return bytes.nextByte(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } + + /** + * This class is the {@link RopeByteString} equivalent for + * {@link ByteArrayInputStream}. + */ + private class RopeInputStream extends InputStream { + // Iterates through the pieces of the rope + private PieceIterator pieceIterator; + // The current piece + private LiteralByteString currentPiece; + // The size of the current piece + private int currentPieceSize; + // The index of the next byte to read in the current piece + private int currentPieceIndex; + // The offset of the start of the current piece in the rope byte string + private int currentPieceOffsetInRope; + // Offset in the buffer at which user called mark(); + private int mark; + + public RopeInputStream() { + initialize(); + } + + @Override + public int read(byte b[], int offset, int length) { + if (b == null) { + throw new NullPointerException(); + } else if (offset < 0 || length < 0 || length > b.length - offset) { + throw new IndexOutOfBoundsException(); + } + return readSkipInternal(b, offset, length); + } + + @Override + public long skip(long length) { + if (length < 0) { + throw new IndexOutOfBoundsException(); + } else if (length > Integer.MAX_VALUE) { + length = Integer.MAX_VALUE; + } + return readSkipInternal(null, 0, (int) length); + } + + /** + * Internal implementation of read and skip. If b != null, then read the + * next {@code length} bytes into the buffer {@code b} at + * offset {@code offset}. If b == null, then skip the next {@code length) + * bytes. + *

+ * This method assumes that all error checking has already happened. + *

+ * Returns the actual number of bytes read or skipped. + */ + private int readSkipInternal(byte b[], int offset, int length) { + int bytesRemaining = length; + while (bytesRemaining > 0) { + advanceIfCurrentPieceFullyRead(); + if (currentPiece == null) { + if (bytesRemaining == length) { + // We didn't manage to read anything + return -1; + } + break; + } else { + // Copy the bytes from this piece. + int currentPieceRemaining = currentPieceSize - currentPieceIndex; + int count = Math.min(currentPieceRemaining, bytesRemaining); + if (b != null) { + currentPiece.copyTo(b, currentPieceIndex, offset, count); + offset += count; + } + currentPieceIndex += count; + bytesRemaining -= count; + } + } + // Return the number of bytes read. + return length - bytesRemaining; + } + + @Override + public int read() throws IOException { + advanceIfCurrentPieceFullyRead(); + if (currentPiece == null) { + return -1; + } else { + return currentPiece.byteAt(currentPieceIndex++) & 0xFF; + } + } + + @Override + public int available() throws IOException { + int bytesRead = currentPieceOffsetInRope + currentPieceIndex; + return RopeByteString.this.size() - bytesRead; + } + + @Override + public boolean markSupported() { + return true; + } + + @Override + public void mark(int readAheadLimit) { + // Set the mark to our position in the byte string + mark = currentPieceOffsetInRope + currentPieceIndex; + } + + @Override + public synchronized void reset() { + // Just reinitialize and skip the specified number of bytes. + initialize(); + readSkipInternal(null, 0, mark); + } + + /** Common initialization code used by both the constructor and reset() */ + private void initialize() { + pieceIterator = new PieceIterator(RopeByteString.this); + currentPiece = pieceIterator.next(); + currentPieceSize = currentPiece.size(); + currentPieceIndex = 0; + currentPieceOffsetInRope = 0; + } + + /** + * Skips to the next piece if we have read all the data in the current + * piece. Sets currentPiece to null if we have reached the end of the + * input. + */ + private void advanceIfCurrentPieceFullyRead() { + if (currentPiece != null && currentPieceIndex == currentPieceSize) { + // Generally, we can only go through this loop at most once, since + // empty strings can't end up in a rope. But better to test. + currentPieceOffsetInRope += currentPieceSize; + currentPieceIndex = 0; + if (pieceIterator.hasNext()) { + currentPiece = pieceIterator.next(); + currentPieceSize = currentPiece.size(); + } else { + currentPiece = null; + currentPieceSize = 0; + } + } + } + } +} diff --git a/java/src/main/java/com/google/protobuf/RpcUtil.java b/java/src/main/java/com/google/protobuf/RpcUtil.java index b1b959a..856f0a5 100644 --- a/java/src/main/java/com/google/protobuf/RpcUtil.java +++ b/java/src/main/java/com/google/protobuf/RpcUtil.java @@ -91,9 +91,8 @@ public final class RpcUtil { @SuppressWarnings("unchecked") private static Type copyAsType( final Type typeDefaultInstance, final Message source) { - return (Type)typeDefaultInstance.newBuilderForType() - .mergeFrom(source) - .build(); + return (Type) typeDefaultInstance + .newBuilderForType().mergeFrom(source).build(); } /** diff --git a/java/src/main/java/com/google/protobuf/ServiceException.java b/java/src/main/java/com/google/protobuf/ServiceException.java index c043a77..cde669d 100644 --- a/java/src/main/java/com/google/protobuf/ServiceException.java +++ b/java/src/main/java/com/google/protobuf/ServiceException.java @@ -35,10 +35,18 @@ package com.google.protobuf; * * @author cpovirk@google.com (Chris Povirk) */ -public final class ServiceException extends Exception { +public class ServiceException extends Exception { private static final long serialVersionUID = -1219262335729891920L; public ServiceException(final String message) { super(message); } + + public ServiceException(final Throwable cause) { + super(cause); + } + + public ServiceException(final String message, final Throwable cause) { + super(message, cause); + } } diff --git a/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java b/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java new file mode 100644 index 0000000..4bfc9f3 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java @@ -0,0 +1,241 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +/** + * {@code SingleFieldBuilder} implements a structure that a protocol + * message uses to hold a single field of another protocol message. It supports + * the classical use case of setting an immutable {@link Message} as the value + * of the field and is highly optimized around this. + *
+ * It also supports the additional use case of setting a {@link Message.Builder} + * as the field and deferring conversion of that {@code Builder} + * to an immutable {@code Message}. In this way, it's possible to maintain + * a tree of {@code Builder}'s that acts as a fully read/write data + * structure. + *
+ * Logically, one can think of a tree of builders as converting the entire tree + * to messages when build is called on the root or when any method is called + * that desires a Message instead of a Builder. In terms of the implementation, + * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder} + * classes cache messages that were created so that messages only need to be + * created when some change occured in its builder or a builder for one of its + * descendants. + * + * @param the type of message for the field + * @param the type of builder for the field + * @param the common interface for the message and the builder + * + * @author jonp@google.com (Jon Perlow) + */ +public class SingleFieldBuilder + + implements GeneratedMessage.BuilderParent { + + // Parent to send changes to. + private GeneratedMessage.BuilderParent parent; + + // Invariant: one of builder or message fields must be non-null. + + // If set, this is the case where we are backed by a builder. In this case, + // message field represents a cached message for the builder (or null if + // there is no cached message). + private BType builder; + + // If builder is non-null, this represents a cached message from the builder. + // If builder is null, this is the authoritative message for the field. + private MType message; + + // Indicates that we've built a message and so we are now obligated + // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener. + private boolean isClean; + + public SingleFieldBuilder( + MType message, + GeneratedMessage.BuilderParent parent, + boolean isClean) { + if (message == null) { + throw new NullPointerException(); + } + this.message = message; + this.parent = parent; + this.isClean = isClean; + } + + public void dispose() { + // Null out parent so we stop sending it invalidations. + parent = null; + } + + /** + * Get the message for the field. If the message is currently stored + * as a {@code Builder}, it is converted to a {@code Message} by + * calling {@link Message.Builder#buildPartial} on it. If no message has + * been set, returns the default instance of the message. + * + * @return the message for the field + */ + @SuppressWarnings("unchecked") + public MType getMessage() { + if (message == null) { + // If message is null, the invariant is that we must be have a builder. + message = (MType) builder.buildPartial(); + } + return message; + } + + /** + * Builds the message and returns it. + * + * @return the message + */ + public MType build() { + // Now that build has been called, we are required to dispatch + // invalidations. + isClean = true; + return getMessage(); + } + + /** + * Gets a builder for the field. If no builder has been created yet, a + * builder is created on demand by calling {@link Message#toBuilder}. + * + * @return The builder for the field + */ + @SuppressWarnings("unchecked") + public BType getBuilder() { + if (builder == null) { + // builder.mergeFrom() on a fresh builder + // does not create any sub-objects with independent clean/dirty states, + // therefore setting the builder itself to clean without actually calling + // build() cannot break any invariants. + builder = (BType) message.newBuilderForType(this); + builder.mergeFrom(message); // no-op if message is the default message + builder.markClean(); + } + return builder; + } + + /** + * Gets the base class interface for the field. This may either be a builder + * or a message. It will return whatever is more efficient. + * + * @return the message or builder for the field as the base class interface + */ + @SuppressWarnings("unchecked") + public IType getMessageOrBuilder() { + if (builder != null) { + return (IType) builder; + } else { + return (IType) message; + } + } + + /** + * Sets a message for the field replacing any existing value. + * + * @param message the message to set + * @return the builder + */ + public SingleFieldBuilder setMessage( + MType message) { + if (message == null) { + throw new NullPointerException(); + } + this.message = message; + if (builder != null) { + builder.dispose(); + builder = null; + } + onChanged(); + return this; + } + + /** + * Merges the field from another field. + * + * @param value the value to merge from + * @return the builder + */ + public SingleFieldBuilder mergeFrom( + MType value) { + if (builder == null && message == message.getDefaultInstanceForType()) { + message = value; + } else { + getBuilder().mergeFrom(value); + } + onChanged(); + return this; + } + + /** + * Clears the value of the field. + * + * @return the builder + */ + @SuppressWarnings("unchecked") + public SingleFieldBuilder clear() { + message = (MType) (message != null ? + message.getDefaultInstanceForType() : + builder.getDefaultInstanceForType()); + if (builder != null) { + builder.dispose(); + builder = null; + } + onChanged(); + return this; + } + + /** + * Called when a the builder or one of its nested children has changed + * and any parent should be notified of its invalidation. + */ + private void onChanged() { + // If builder is null, this is the case where onChanged is being called + // from setMessage or clear. + if (builder != null) { + message = null; + } + if (isClean && parent != null) { + parent.markDirty(); + + // Don't keep dispatching invalidations until build is called again. + isClean = false; + } + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void markDirty() { + onChanged(); + } +} diff --git a/java/src/main/java/com/google/protobuf/SmallSortedMap.java b/java/src/main/java/com/google/protobuf/SmallSortedMap.java new file mode 100644 index 0000000..c6cad6a --- /dev/null +++ b/java/src/main/java/com/google/protobuf/SmallSortedMap.java @@ -0,0 +1,618 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.TreeMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedMap; + +/** + * A custom map implementation from FieldDescriptor to Object optimized to + * minimize the number of memory allocations for instances with a small number + * of mappings. The implementation stores the first {@code k} mappings in an + * array for a configurable value of {@code k}, allowing direct access to the + * corresponding {@code Entry}s without the need to create an Iterator. The + * remaining entries are stored in an overflow map. Iteration over the entries + * in the map should be done as follows: + * + *

   {@code
+ * for (int i = 0; i < fieldMap.getNumArrayEntries(); i++) {
+ *   process(fieldMap.getArrayEntryAt(i));
+ * }
+ * for (Map.Entry entry : fieldMap.getOverflowEntries()) {
+ *   process(entry);
+ * }
+ * }
+ * + * The resulting iteration is in order of ascending field tag number. The + * object returned by {@link #entrySet()} adheres to the same contract but is + * less efficient as it necessarily involves creating an object for iteration. + *

+ * The tradeoff for this memory efficiency is that the worst case running time + * of the {@code put()} operation is {@code O(k + lg n)}, which happens when + * entries are added in descending order. {@code k} should be chosen such that + * it covers enough common cases without adversely affecting larger maps. In + * practice, the worst case scenario does not happen for extensions because + * extension fields are serialized and deserialized in order of ascending tag + * number, but the worst case scenario can happen for DynamicMessages. + *

+ * The running time for all other operations is similar to that of + * {@code TreeMap}. + *

+ * Instances are not thread-safe until {@link #makeImmutable()} is called, + * after which any modifying operation will result in an + * {@link UnsupportedOperationException}. + * + * @author darick@google.com Darick Tong + */ +// This class is final for all intents and purposes because the constructor is +// private. However, the FieldDescriptor-specific logic is encapsulated in +// a subclass to aid testability of the core logic. +class SmallSortedMap, V> extends AbstractMap { + + /** + * Creates a new instance for mapping FieldDescriptors to their values. + * The {@link #makeImmutable()} implementation will convert the List values + * of any repeated fields to unmodifiable lists. + * + * @param arraySize The size of the entry array containing the + * lexicographically smallest mappings. + */ + static > + SmallSortedMap newFieldMap(int arraySize) { + return new SmallSortedMap(arraySize) { + @Override + @SuppressWarnings("unchecked") + public void makeImmutable() { + if (!isImmutable()) { + for (int i = 0; i < getNumArrayEntries(); i++) { + final Map.Entry entry = + getArrayEntryAt(i); + if (entry.getKey().isRepeated()) { + final List value = (List) entry.getValue(); + entry.setValue(Collections.unmodifiableList(value)); + } + } + for (Map.Entry entry : + getOverflowEntries()) { + if (entry.getKey().isRepeated()) { + final List value = (List) entry.getValue(); + entry.setValue(Collections.unmodifiableList(value)); + } + } + } + super.makeImmutable(); + } + }; + } + + /** + * Creates a new instance for testing. + * + * @param arraySize The size of the entry array containing the + * lexicographically smallest mappings. + */ + static , V> SmallSortedMap newInstanceForTest( + int arraySize) { + return new SmallSortedMap(arraySize); + } + + private final int maxArraySize; + // The "entry array" is actually a List because generic arrays are not + // allowed. ArrayList also nicely handles the entry shifting on inserts and + // removes. + private List entryList; + private Map overflowEntries; + private boolean isImmutable; + // The EntrySet is a stateless view of the Map. It's initialized the first + // time it is requested and reused henceforth. + private volatile EntrySet lazyEntrySet; + + /** + * @code arraySize Size of the array in which the lexicographically smallest + * mappings are stored. (i.e. the {@code k} referred to in the class + * documentation). + */ + private SmallSortedMap(int arraySize) { + this.maxArraySize = arraySize; + this.entryList = Collections.emptyList(); + this.overflowEntries = Collections.emptyMap(); + } + + /** Make this map immutable from this point forward. */ + public void makeImmutable() { + if (!isImmutable) { + // Note: There's no need to wrap the entryList in an unmodifiableList + // because none of the list's accessors are exposed. The iterator() of + // overflowEntries, on the other hand, is exposed so it must be made + // unmodifiable. + overflowEntries = overflowEntries.isEmpty() ? + Collections.emptyMap() : + Collections.unmodifiableMap(overflowEntries); + isImmutable = true; + } + } + + /** @return Whether {@link #makeImmutable()} has been called. */ + public boolean isImmutable() { + return isImmutable; + } + + /** @return The number of entries in the entry array. */ + public int getNumArrayEntries() { + return entryList.size(); + } + + /** @return The array entry at the given {@code index}. */ + public Map.Entry getArrayEntryAt(int index) { + return entryList.get(index); + } + + /** @return There number of overflow entries. */ + public int getNumOverflowEntries() { + return overflowEntries.size(); + } + + /** @return An iterable over the overflow entries. */ + public Iterable> getOverflowEntries() { + return overflowEntries.isEmpty() ? + EmptySet.>iterable() : + overflowEntries.entrySet(); + } + + @Override + public int size() { + return entryList.size() + overflowEntries.size(); + } + + /** + * The implementation throws a {@code ClassCastException} if o is not an + * object of type {@code K}. + * + * {@inheritDoc} + */ + @Override + public boolean containsKey(Object o) { + @SuppressWarnings("unchecked") + final K key = (K) o; + return binarySearchInArray(key) >= 0 || overflowEntries.containsKey(key); + } + + /** + * The implementation throws a {@code ClassCastException} if o is not an + * object of type {@code K}. + * + * {@inheritDoc} + */ + @Override + public V get(Object o) { + @SuppressWarnings("unchecked") + final K key = (K) o; + final int index = binarySearchInArray(key); + if (index >= 0) { + return entryList.get(index).getValue(); + } + return overflowEntries.get(key); + } + + @Override + public V put(K key, V value) { + checkMutable(); + final int index = binarySearchInArray(key); + if (index >= 0) { + // Replace existing array entry. + return entryList.get(index).setValue(value); + } + ensureEntryArrayMutable(); + final int insertionPoint = -(index + 1); + if (insertionPoint >= maxArraySize) { + // Put directly in overflow. + return getOverflowEntriesMutable().put(key, value); + } + // Insert new Entry in array. + if (entryList.size() == maxArraySize) { + // Shift the last array entry into overflow. + final Entry lastEntryInArray = entryList.remove(maxArraySize - 1); + getOverflowEntriesMutable().put(lastEntryInArray.getKey(), + lastEntryInArray.getValue()); + } + entryList.add(insertionPoint, new Entry(key, value)); + return null; + } + + @Override + public void clear() { + checkMutable(); + if (!entryList.isEmpty()) { + entryList.clear(); + } + if (!overflowEntries.isEmpty()) { + overflowEntries.clear(); + } + } + + /** + * The implementation throws a {@code ClassCastException} if o is not an + * object of type {@code K}. + * + * {@inheritDoc} + */ + @Override + public V remove(Object o) { + checkMutable(); + @SuppressWarnings("unchecked") + final K key = (K) o; + final int index = binarySearchInArray(key); + if (index >= 0) { + return removeArrayEntryAt(index); + } + // overflowEntries might be Collections.unmodifiableMap(), so only + // call remove() if it is non-empty. + if (overflowEntries.isEmpty()) { + return null; + } else { + return overflowEntries.remove(key); + } + } + + private V removeArrayEntryAt(int index) { + checkMutable(); + final V removed = entryList.remove(index).getValue(); + if (!overflowEntries.isEmpty()) { + // Shift the first entry in the overflow to be the last entry in the + // array. + final Iterator> iterator = + getOverflowEntriesMutable().entrySet().iterator(); + entryList.add(new Entry(iterator.next())); + iterator.remove(); + } + return removed; + } + + /** + * @param key The key to find in the entry array. + * @return The returned integer position follows the same semantics as the + * value returned by {@link java.util.Arrays#binarySearch()}. + */ + private int binarySearchInArray(K key) { + int left = 0; + int right = entryList.size() - 1; + + // Optimization: For the common case in which entries are added in + // ascending tag order, check the largest element in the array before + // doing a full binary search. + if (right >= 0) { + int cmp = key.compareTo(entryList.get(right).getKey()); + if (cmp > 0) { + return -(right + 2); // Insert point is after "right". + } else if (cmp == 0) { + return right; + } + } + + while (left <= right) { + int mid = (left + right) / 2; + int cmp = key.compareTo(entryList.get(mid).getKey()); + if (cmp < 0) { + right = mid - 1; + } else if (cmp > 0) { + left = mid + 1; + } else { + return mid; + } + } + return -(left + 1); + } + + /** + * Similar to the AbstractMap implementation of {@code keySet()} and + * {@code values()}, the entry set is created the first time this method is + * called, and returned in response to all subsequent calls. + * + * {@inheritDoc} + */ + @Override + public Set> entrySet() { + if (lazyEntrySet == null) { + lazyEntrySet = new EntrySet(); + } + return lazyEntrySet; + } + + /** + * @throws UnsupportedOperationException if {@link #makeImmutable()} has + * has been called. + */ + private void checkMutable() { + if (isImmutable) { + throw new UnsupportedOperationException(); + } + } + + /** + * @return a {@link SortedMap} to which overflow entries mappings can be + * added or removed. + * @throws UnsupportedOperationException if {@link #makeImmutable()} has been + * called. + */ + @SuppressWarnings("unchecked") + private SortedMap getOverflowEntriesMutable() { + checkMutable(); + if (overflowEntries.isEmpty() && !(overflowEntries instanceof TreeMap)) { + overflowEntries = new TreeMap(); + } + return (SortedMap) overflowEntries; + } + + /** + * Lazily creates the entry list. Any code that adds to the list must first + * call this method. + */ + private void ensureEntryArrayMutable() { + checkMutable(); + if (entryList.isEmpty() && !(entryList instanceof ArrayList)) { + entryList = new ArrayList(maxArraySize); + } + } + + /** + * Entry implementation that implements Comparable in order to support + * binary search within the entry array. Also checks mutability in + * {@link #setValue()}. + */ + private class Entry implements Map.Entry, Comparable { + + private final K key; + private V value; + + Entry(Map.Entry copy) { + this(copy.getKey(), copy.getValue()); + } + + Entry(K key, V value) { + this.key = key; + this.value = value; + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public K getKey() { + return key; + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public V getValue() { + return value; + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public int compareTo(Entry other) { + return getKey().compareTo(other.getKey()); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public V setValue(V newValue) { + checkMutable(); + final V oldValue = this.value; + this.value = newValue; + return oldValue; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Map.Entry)) { + return false; + } + @SuppressWarnings("unchecked") + Map.Entry other = (Map.Entry) o; + return equals(key, other.getKey()) && equals(value, other.getValue()); + } + + @Override + public int hashCode() { + return (key == null ? 0 : key.hashCode()) ^ + (value == null ? 0 : value.hashCode()); + } + + @Override + public String toString() { + return key + "=" + value; + } + + /** equals() that handles null values. */ + private boolean equals(Object o1, Object o2) { + return o1 == null ? o2 == null : o1.equals(o2); + } + } + + /** + * Stateless view of the entries in the field map. + */ + private class EntrySet extends AbstractSet> { + + @Override + public Iterator> iterator() { + return new EntryIterator(); + } + + @Override + public int size() { + return SmallSortedMap.this.size(); + } + + /** + * Throws a {@link ClassCastException} if o is not of the expected type. + * + * {@inheritDoc} + */ + @Override + public boolean contains(Object o) { + @SuppressWarnings("unchecked") + final Map.Entry entry = (Map.Entry) o; + final V existing = get(entry.getKey()); + final V value = entry.getValue(); + return existing == value || + (existing != null && existing.equals(value)); + } + + @Override + public boolean add(Map.Entry entry) { + if (!contains(entry)) { + put(entry.getKey(), entry.getValue()); + return true; + } + return false; + } + + /** + * Throws a {@link ClassCastException} if o is not of the expected type. + * + * {@inheritDoc} + */ + @Override + public boolean remove(Object o) { + @SuppressWarnings("unchecked") + final Map.Entry entry = (Map.Entry) o; + if (contains(entry)) { + SmallSortedMap.this.remove(entry.getKey()); + return true; + } + return false; + } + + @Override + public void clear() { + SmallSortedMap.this.clear(); + } + } + + /** + * Iterator implementation that switches from the entry array to the overflow + * entries appropriately. + */ + private class EntryIterator implements Iterator> { + + private int pos = -1; + private boolean nextCalledBeforeRemove; + private Iterator> lazyOverflowIterator; + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public boolean hasNext() { + return (pos + 1) < entryList.size() || + getOverflowIterator().hasNext(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public Map.Entry next() { + nextCalledBeforeRemove = true; + // Always increment pos so that we know whether the last returned value + // was from the array or from overflow. + if (++pos < entryList.size()) { + return entryList.get(pos); + } + return getOverflowIterator().next(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void remove() { + if (!nextCalledBeforeRemove) { + throw new IllegalStateException("remove() was called before next()"); + } + nextCalledBeforeRemove = false; + checkMutable(); + + if (pos < entryList.size()) { + removeArrayEntryAt(pos--); + } else { + getOverflowIterator().remove(); + } + } + + /** + * It is important to create the overflow iterator only after the array + * entries have been iterated over because the overflow entry set changes + * when the client calls remove() on the array entries, which invalidates + * any existing iterators. + */ + private Iterator> getOverflowIterator() { + if (lazyOverflowIterator == null) { + lazyOverflowIterator = overflowEntries.entrySet().iterator(); + } + return lazyOverflowIterator; + } + } + + /** + * Helper class that holds immutable instances of an Iterable/Iterator that + * we return when the overflow entries is empty. This eliminates the creation + * of an Iterator object when there is nothing to iterate over. + */ + private static class EmptySet { + + private static final Iterator ITERATOR = new Iterator() { + //@Override (Java 1.6 override semantics, but we must support 1.5) + public boolean hasNext() { + return false; + } + //@Override (Java 1.6 override semantics, but we must support 1.5) + public Object next() { + throw new NoSuchElementException(); + } + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void remove() { + throw new UnsupportedOperationException(); + } + }; + + private static final Iterable ITERABLE = new Iterable() { + //@Override (Java 1.6 override semantics, but we must support 1.5) + public Iterator iterator() { + return ITERATOR; + } + }; + + @SuppressWarnings("unchecked") + static Iterable iterable() { + return (Iterable) ITERABLE; + } + } +} diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java index cb23f0c..5512ca2 100644 --- a/java/src/main/java/com/google/protobuf/TextFormat.java +++ b/java/src/main/java/com/google/protobuf/TextFormat.java @@ -31,63 +31,119 @@ package com.google.protobuf; import com.google.protobuf.Descriptors.Descriptor; -import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.EnumValueDescriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; import java.io.IOException; -import java.nio.CharBuffer; import java.math.BigInteger; +import java.nio.CharBuffer; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; /** - * Provide ascii text parsing and formatting support for proto2 instances. + * Provide text parsing and formatting support for proto2 instances. * The implementation largely follows google/protobuf/text_format.cc. * * @author wenboz@google.com Wenbo Zhu * @author kenton@google.com Kenton Varda */ public final class TextFormat { - private TextFormat() { - } + private TextFormat() {} + + private static final Logger logger = + Logger.getLogger(TextFormat.class.getName()); + + private static final Printer DEFAULT_PRINTER = new Printer(); + private static final Printer SINGLE_LINE_PRINTER = + (new Printer()).setSingleLineMode(true); + private static final Printer UNICODE_PRINTER = + (new Printer()).setEscapeNonAscii(false); /** * Outputs a textual representation of the Protocol Message supplied into * the parameter output. (This representation is the new version of the * classic "ProtocolPrinter" output from the original Protocol Buffer system) */ - public static void print(final Message message, final Appendable output) - throws IOException { - final TextGenerator generator = new TextGenerator(output); - print(message, generator); + public static void print( + final MessageOrBuilder message, final Appendable output) + throws IOException { + DEFAULT_PRINTER.print(message, new TextGenerator(output)); } /** Outputs a textual representation of {@code fields} to {@code output}. */ public static void print(final UnknownFieldSet fields, final Appendable output) throws IOException { - final TextGenerator generator = new TextGenerator(output); - printUnknownFields(fields, generator); + DEFAULT_PRINTER.printUnknownFields(fields, new TextGenerator(output)); + } + + /** + * Same as {@code print()}, except that non-ASCII characters are not + * escaped. + */ + public static void printUnicode( + final MessageOrBuilder message, final Appendable output) + throws IOException { + UNICODE_PRINTER.print(message, new TextGenerator(output)); + } + + /** + * Same as {@code print()}, except that non-ASCII characters are not + * escaped. + */ + public static void printUnicode(final UnknownFieldSet fields, + final Appendable output) + throws IOException { + UNICODE_PRINTER.printUnknownFields(fields, new TextGenerator(output)); + } + + /** + * Generates a human readable form of this message, useful for debugging and + * other purposes, with no newline characters. + */ + public static String shortDebugString(final MessageOrBuilder message) { + try { + final StringBuilder sb = new StringBuilder(); + SINGLE_LINE_PRINTER.print(message, new TextGenerator(sb)); + // Single line mode currently might have an extra space at the end. + return sb.toString().trim(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + /** + * Generates a human readable form of the unknown fields, useful for debugging + * and other purposes, with no newline characters. + */ + public static String shortDebugString(final UnknownFieldSet fields) { + try { + final StringBuilder sb = new StringBuilder(); + SINGLE_LINE_PRINTER.printUnknownFields(fields, new TextGenerator(sb)); + // Single line mode currently might have an extra space at the end. + return sb.toString().trim(); + } catch (IOException e) { + throw new IllegalStateException(e); + } } /** * Like {@code print()}, but writes directly to a {@code String} and * returns it. */ - public static String printToString(final Message message) { + public static String printToString(final MessageOrBuilder message) { try { final StringBuilder text = new StringBuilder(); print(message, text); return text.toString(); } catch (IOException e) { - throw new RuntimeException( - "Writing to a StringBuilder threw an IOException (should never " + - "happen).", e); + throw new IllegalStateException(e); } } @@ -101,28 +157,43 @@ public final class TextFormat { print(fields, text); return text.toString(); } catch (IOException e) { - throw new RuntimeException( - "Writing to a StringBuilder threw an IOException (should never " + - "happen).", e); + throw new IllegalStateException(e); } } - private static void print(final Message message, - final TextGenerator generator) - throws IOException { - for (final Map.Entry field : - message.getAllFields().entrySet()) { - printField(field.getKey(), field.getValue(), generator); + /** + * Same as {@code printToString()}, except that non-ASCII characters + * in string type fields are not escaped in backslash+octals. + */ + public static String printToUnicodeString(final MessageOrBuilder message) { + try { + final StringBuilder text = new StringBuilder(); + UNICODE_PRINTER.print(message, new TextGenerator(text)); + return text.toString(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + /** + * Same as {@code printToString()}, except that non-ASCII characters + * in string type fields are not escaped in backslash+octals. + */ + public static String printToUnicodeString(final UnknownFieldSet fields) { + try { + final StringBuilder text = new StringBuilder(); + UNICODE_PRINTER.printUnknownFields(fields, new TextGenerator(text)); + return text.toString(); + } catch (IOException e) { + throw new IllegalStateException(e); } - printUnknownFields(message.getUnknownFields(), generator); } public static void printField(final FieldDescriptor field, final Object value, final Appendable output) throws IOException { - final TextGenerator generator = new TextGenerator(output); - printField(field, value, generator); + DEFAULT_PRINTER.printField(field, value, new TextGenerator(output)); } public static String printFieldToString(final FieldDescriptor field, @@ -132,173 +203,298 @@ public final class TextFormat { printField(field, value, text); return text.toString(); } catch (IOException e) { - throw new RuntimeException( - "Writing to a StringBuilder threw an IOException (should never " + - "happen).", e); + throw new IllegalStateException(e); } } - private static void printField(final FieldDescriptor field, - final Object value, - final TextGenerator generator) - throws IOException { - if (field.isRepeated()) { - // Repeated field. Print each element. - for (final Object element : (List) value) { - printSingleField(field, element, generator); - } - } else { - printSingleField(field, value, generator); + /** + * Outputs a textual representation of the value of given field value. + * + * @param field the descriptor of the field + * @param value the value of the field + * @param output the output to which to append the formatted value + * @throws ClassCastException if the value is not appropriate for the + * given field descriptor + * @throws IOException if there is an exception writing to the output + */ + public static void printFieldValue(final FieldDescriptor field, + final Object value, + final Appendable output) + throws IOException { + DEFAULT_PRINTER.printFieldValue(field, value, new TextGenerator(output)); + } + + /** + * Outputs a textual representation of the value of an unknown field. + * + * @param tag the field's tag number + * @param value the value of the field + * @param output the output to which to append the formatted value + * @throws ClassCastException if the value is not appropriate for the + * given field descriptor + * @throws IOException if there is an exception writing to the output + */ + public static void printUnknownFieldValue(final int tag, + final Object value, + final Appendable output) + throws IOException { + printUnknownFieldValue(tag, value, new TextGenerator(output)); + } + + private static void printUnknownFieldValue(final int tag, + final Object value, + final TextGenerator generator) + throws IOException { + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + generator.print(unsignedToString((Long) value)); + break; + case WireFormat.WIRETYPE_FIXED32: + generator.print( + String.format((Locale) null, "0x%08x", (Integer) value)); + break; + case WireFormat.WIRETYPE_FIXED64: + generator.print(String.format((Locale) null, "0x%016x", (Long) value)); + break; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + generator.print("\""); + generator.print(escapeBytes((ByteString) value)); + generator.print("\""); + break; + case WireFormat.WIRETYPE_START_GROUP: + DEFAULT_PRINTER.printUnknownFields((UnknownFieldSet) value, generator); + break; + default: + throw new IllegalArgumentException("Bad tag: " + tag); } } - private static void printSingleField(final FieldDescriptor field, - final Object value, - final TextGenerator generator) - throws IOException { - if (field.isExtension()) { - generator.print("["); - // We special-case MessageSet elements for compatibility with proto1. - if (field.getContainingType().getOptions().getMessageSetWireFormat() - && (field.getType() == FieldDescriptor.Type.MESSAGE) - && (field.isOptional()) - // object equality - && (field.getExtensionScope() == field.getMessageType())) { - generator.print(field.getMessageType().getFullName()); - } else { - generator.print(field.getFullName()); + /** Helper class for converting protobufs to text. */ + private static final class Printer { + /** Whether to omit newlines from the output. */ + boolean singleLineMode = false; + + /** Whether to escape non ASCII characters with backslash and octal. */ + boolean escapeNonAscii = true; + + private Printer() {} + + /** Setter of singleLineMode */ + private Printer setSingleLineMode(boolean singleLineMode) { + this.singleLineMode = singleLineMode; + return this; + } + + /** Setter of escapeNonAscii */ + private Printer setEscapeNonAscii(boolean escapeNonAscii) { + this.escapeNonAscii = escapeNonAscii; + return this; + } + + private void print( + final MessageOrBuilder message, final TextGenerator generator) + throws IOException { + for (Map.Entry field + : message.getAllFields().entrySet()) { + printField(field.getKey(), field.getValue(), generator); } - generator.print("]"); - } else { - if (field.getType() == FieldDescriptor.Type.GROUP) { - // Groups must be serialized with their original capitalization. - generator.print(field.getMessageType().getName()); + printUnknownFields(message.getUnknownFields(), generator); + } + + private void printField(final FieldDescriptor field, final Object value, + final TextGenerator generator) throws IOException { + if (field.isRepeated()) { + // Repeated field. Print each element. + for (Object element : (List) value) { + printSingleField(field, element, generator); + } } else { - generator.print(field.getName()); + printSingleField(field, value, generator); } } - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - generator.print(" {\n"); - generator.indent(); - } else { - generator.print(": "); - } + private void printSingleField(final FieldDescriptor field, + final Object value, + final TextGenerator generator) + throws IOException { + if (field.isExtension()) { + generator.print("["); + // We special-case MessageSet elements for compatibility with proto1. + if (field.getContainingType().getOptions().getMessageSetWireFormat() + && (field.getType() == FieldDescriptor.Type.MESSAGE) + && (field.isOptional()) + // object equality + && (field.getExtensionScope() == field.getMessageType())) { + generator.print(field.getMessageType().getFullName()); + } else { + generator.print(field.getFullName()); + } + generator.print("]"); + } else { + if (field.getType() == FieldDescriptor.Type.GROUP) { + // Groups must be serialized with their original capitalization. + generator.print(field.getMessageType().getName()); + } else { + generator.print(field.getName()); + } + } - printFieldValue(field, value, generator); + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (singleLineMode) { + generator.print(" { "); + } else { + generator.print(" {\n"); + generator.indent(); + } + } else { + generator.print(": "); + } + + printFieldValue(field, value, generator); - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - generator.outdent(); - generator.print("}"); + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (singleLineMode) { + generator.print("} "); + } else { + generator.outdent(); + generator.print("}\n"); + } + } else { + if (singleLineMode) { + generator.print(" "); + } else { + generator.print("\n"); + } + } } - generator.print("\n"); - } - private static void printFieldValue(final FieldDescriptor field, - final Object value, - final TextGenerator generator) - throws IOException { - switch (field.getType()) { - case INT32: - case INT64: - case SINT32: - case SINT64: - case SFIXED32: - case SFIXED64: - case FLOAT: - case DOUBLE: - case BOOL: - // Good old toString() does what we want for these types. - generator.print(value.toString()); - break; + private void printFieldValue(final FieldDescriptor field, + final Object value, + final TextGenerator generator) + throws IOException { + switch (field.getType()) { + case INT32: + case SINT32: + case SFIXED32: + generator.print(((Integer) value).toString()); + break; - case UINT32: - case FIXED32: - generator.print(unsignedToString((Integer) value)); - break; + case INT64: + case SINT64: + case SFIXED64: + generator.print(((Long) value).toString()); + break; - case UINT64: - case FIXED64: - generator.print(unsignedToString((Long) value)); - break; + case BOOL: + generator.print(((Boolean) value).toString()); + break; - case STRING: - generator.print("\""); - generator.print(escapeText((String) value)); - generator.print("\""); - break; + case FLOAT: + generator.print(((Float) value).toString()); + break; - case BYTES: - generator.print("\""); - generator.print(escapeBytes((ByteString) value)); - generator.print("\""); - break; + case DOUBLE: + generator.print(((Double) value).toString()); + break; - case ENUM: - generator.print(((EnumValueDescriptor) value).getName()); - break; + case UINT32: + case FIXED32: + generator.print(unsignedToString((Integer) value)); + break; - case MESSAGE: - case GROUP: - print((Message) value, generator); - break; - } - } + case UINT64: + case FIXED64: + generator.print(unsignedToString((Long) value)); + break; - private static void printUnknownFields(final UnknownFieldSet unknownFields, - final TextGenerator generator) - throws IOException { - for (final Map.Entry entry : - unknownFields.asMap().entrySet()) { - final String prefix = entry.getKey().toString() + ": "; - final UnknownFieldSet.Field field = entry.getValue(); + case STRING: + generator.print("\""); + generator.print(escapeNonAscii ? + escapeText((String) value) : + escapeDoubleQuotesAndBackslashes((String) value)); + generator.print("\""); + break; - for (final long value : field.getVarintList()) { - generator.print(entry.getKey().toString()); - generator.print(": "); - generator.print(unsignedToString(value)); - generator.print("\n"); + case BYTES: + generator.print("\""); + if (value instanceof ByteString) { + generator.print(escapeBytes((ByteString) value)); + } else { + generator.print(escapeBytes((byte[]) value)); + } + generator.print("\""); + break; + + case ENUM: + generator.print(((EnumValueDescriptor) value).getName()); + break; + + case MESSAGE: + case GROUP: + print((Message) value, generator); + break; } - for (final int value : field.getFixed32List()) { - generator.print(entry.getKey().toString()); - generator.print(": "); - generator.print(String.format((Locale) null, "0x%08x", value)); - generator.print("\n"); + } + + private void printUnknownFields(final UnknownFieldSet unknownFields, + final TextGenerator generator) + throws IOException { + for (Map.Entry entry : + unknownFields.asMap().entrySet()) { + final int number = entry.getKey(); + final UnknownFieldSet.Field field = entry.getValue(); + printUnknownField(number, WireFormat.WIRETYPE_VARINT, + field.getVarintList(), generator); + printUnknownField(number, WireFormat.WIRETYPE_FIXED32, + field.getFixed32List(), generator); + printUnknownField(number, WireFormat.WIRETYPE_FIXED64, + field.getFixed64List(), generator); + printUnknownField(number, WireFormat.WIRETYPE_LENGTH_DELIMITED, + field.getLengthDelimitedList(), generator); + for (final UnknownFieldSet value : field.getGroupList()) { + generator.print(entry.getKey().toString()); + if (singleLineMode) { + generator.print(" { "); + } else { + generator.print(" {\n"); + generator.indent(); + } + printUnknownFields(value, generator); + if (singleLineMode) { + generator.print("} "); + } else { + generator.outdent(); + generator.print("}\n"); + } + } } - for (final long value : field.getFixed64List()) { - generator.print(entry.getKey().toString()); + } + + private void printUnknownField(final int number, + final int wireType, + final List values, + final TextGenerator generator) + throws IOException { + for (final Object value : values) { + generator.print(String.valueOf(number)); generator.print(": "); - generator.print(String.format((Locale) null, "0x%016x", value)); - generator.print("\n"); - } - for (final ByteString value : field.getLengthDelimitedList()) { - generator.print(entry.getKey().toString()); - generator.print(": \""); - generator.print(escapeBytes(value)); - generator.print("\"\n"); - } - for (final UnknownFieldSet value : field.getGroupList()) { - generator.print(entry.getKey().toString()); - generator.print(" {\n"); - generator.indent(); - printUnknownFields(value, generator); - generator.outdent(); - generator.print("}\n"); + printUnknownFieldValue(wireType, value, generator); + generator.print(singleLineMode ? " " : "\n"); } } } /** Convert an unsigned 32-bit integer to a string. */ - private static String unsignedToString(final int value) { + public static String unsignedToString(final int value) { if (value >= 0) { return Integer.toString(value); } else { - return Long.toString(((long) value) & 0x00000000FFFFFFFFL); + return Long.toString(value & 0x00000000FFFFFFFFL); } } /** Convert an unsigned 64-bit integer to a string. */ - private static String unsignedToString(final long value) { + public static String unsignedToString(final long value) { if (value >= 0) { return Long.toString(value); } else { @@ -313,9 +509,9 @@ public final class TextFormat { * An inner class for writing text to the output stream. */ private static final class TextGenerator { - private Appendable output; - private boolean atStartOfLine = true; + private final Appendable output; private final StringBuilder indent = new StringBuilder(); + private boolean atStartOfLine = true; private TextGenerator(final Appendable output) { this.output = output; @@ -352,17 +548,16 @@ public final class TextFormat { for (int i = 0; i < size; i++) { if (text.charAt(i) == '\n') { - write(text.subSequence(pos, size), i - pos + 1); + write(text.subSequence(pos, i + 1)); pos = i + 1; atStartOfLine = true; } } - write(text.subSequence(pos, size), size - pos); + write(text.subSequence(pos, size)); } - private void write(final CharSequence data, final int size) - throws IOException { - if (size == 0) { + private void write(final CharSequence data) throws IOException { + if (data.length() == 0) { return; } if (atStartOfLine) { @@ -421,7 +616,7 @@ public final class TextFormat { private int previousLine = 0; private int previousColumn = 0; - // We use possesive quantifiers (*+ and ++) because otherwise the Java + // We use possessive quantifiers (*+ and ++) because otherwise the Java // regex matcher has stack overflows on large inputs. private static final Pattern WHITESPACE = Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE); @@ -539,6 +734,14 @@ public final class TextFormat { } /** + * Returns {@code true} if the current token's text is equal to that + * specified. + */ + public boolean lookingAt(String text) { + return currentToken.equals(text); + } + + /** * If the next token is an identifier, consume it and return its value. * Otherwise, throw a {@link ParseException}. */ @@ -551,7 +754,8 @@ public final class TextFormat { (c == '_') || (c == '.')) { // OK } else { - throw parseException("Expected identifier."); + throw parseException( + "Expected identifier. Found '" + currentToken + "'"); } } @@ -561,6 +765,19 @@ public final class TextFormat { } /** + * If the next token is an identifier, consume it and return {@code true}. + * Otherwise, return {@code false} without doing anything. + */ + public boolean tryConsumeIdentifier() { + try { + consumeIdentifier(); + return true; + } catch (ParseException e) { + return false; + } + } + + /** * If the next token is a 32-bit signed integer, consume it and return its * value. Otherwise, throw a {@link ParseException}. */ @@ -603,6 +820,19 @@ public final class TextFormat { } /** + * If the next token is a 64-bit signed integer, consume it and return + * {@code true}. Otherwise, return {@code false} without doing anything. + */ + public boolean tryConsumeInt64() { + try { + consumeInt64(); + return true; + } catch (ParseException e) { + return false; + } + } + + /** * If the next token is a 64-bit unsigned integer, consume it and return its * value. Otherwise, throw a {@link ParseException}. */ @@ -617,6 +847,19 @@ public final class TextFormat { } /** + * If the next token is a 64-bit unsigned integer, consume it and return + * {@code true}. Otherwise, return {@code false} without doing anything. + */ + public boolean tryConsumeUInt64() { + try { + consumeUInt64(); + return true; + } catch (ParseException e) { + return false; + } + } + + /** * If the next token is a double, consume it and return its value. * Otherwise, throw a {@link ParseException}. */ @@ -642,6 +885,19 @@ public final class TextFormat { } /** + * If the next token is a double, consume it and return {@code true}. + * Otherwise, return {@code false} without doing anything. + */ + public boolean tryConsumeDouble() { + try { + consumeDouble(); + return true; + } catch (ParseException e) { + return false; + } + } + + /** * If the next token is a float, consume it and return its value. * Otherwise, throw a {@link ParseException}. */ @@ -667,14 +923,31 @@ public final class TextFormat { } /** + * If the next token is a float, consume it and return {@code true}. + * Otherwise, return {@code false} without doing anything. + */ + public boolean tryConsumeFloat() { + try { + consumeFloat(); + return true; + } catch (ParseException e) { + return false; + } + } + + /** * If the next token is a boolean, consume it and return its value. * Otherwise, throw a {@link ParseException}. */ public boolean consumeBoolean() throws ParseException { - if (currentToken.equals("true")) { + if (currentToken.equals("true") || + currentToken.equals("t") || + currentToken.equals("1")) { nextToken(); return true; - } else if (currentToken.equals("false")) { + } else if (currentToken.equals("false") || + currentToken.equals("f") || + currentToken.equals("0")) { nextToken(); return false; } else { @@ -691,6 +964,19 @@ public final class TextFormat { } /** + * If the next token is a string, consume it and return true. Otherwise, + * return false. + */ + public boolean tryConsumeString() { + try { + consumeString(); + return true; + } catch (ParseException e) { + return false; + } + } + + /** * If the next token is a string, consume it, unescape it as a * {@link ByteString}, and return it. Otherwise, throw a * {@link ParseException}. @@ -710,7 +996,8 @@ public final class TextFormat { * multiple adjacent tokens which are automatically concatenated, like in * C or Python. */ - private void consumeByteString(List list) throws ParseException { + private void consumeByteString(List list) + throws ParseException { final char quote = currentToken.length() > 0 ? currentToken.charAt(0) : '\0'; if (quote != '\"' && quote != '\'') { @@ -740,7 +1027,7 @@ public final class TextFormat { public ParseException parseException(final String description) { // Note: People generally prefer one-based line and column numbers. return new ParseException( - (line + 1) + ":" + (column + 1) + ": " + description); + line + 1, column + 1, description); } /** @@ -751,7 +1038,7 @@ public final class TextFormat { final String description) { // Note: People generally prefer one-based line and column numbers. return new ParseException( - (previousLine + 1) + ":" + (previousColumn + 1) + ": " + description); + previousLine + 1, previousColumn + 1, description); } /** @@ -776,11 +1063,58 @@ public final class TextFormat { public static class ParseException extends IOException { private static final long serialVersionUID = 3196188060225107702L; + private final int line; + private final int column; + + /** Create a new instance, with -1 as the line and column numbers. */ public ParseException(final String message) { - super(message); + this(-1, -1, message); + } + + /** + * Create a new instance + * + * @param line the line number where the parse error occurred, + * using 1-offset. + * @param column the column number where the parser error occurred, + * using 1-offset. + */ + public ParseException(final int line, final int column, + final String message) { + super(Integer.toString(line) + ":" + column + ": " + message); + this.line = line; + this.column = column; + } + + /** + * Return the line where the parse exception occurred, or -1 when + * none is provided. The value is specified as 1-offset, so the first + * line is line 1. + */ + public int getLine() { + return line; + } + + /** + * Return the column where the parse exception occurred, or -1 when + * none is provided. The value is specified as 1-offset, so the first + * line is line 1. + */ + public int getColumn() { + return column; } } + private static final Parser PARSER = Parser.newBuilder().build(); + + /** + * Return a {@link Parser} instance which can parse text-format + * messages. The returned instance is thread-safe. + */ + public static Parser getParser() { + return PARSER; + } + /** * Parse a text-format message from {@code input} and merge the contents * into {@code builder}. @@ -788,7 +1122,7 @@ public final class TextFormat { public static void merge(final Readable input, final Message.Builder builder) throws IOException { - merge(input, ExtensionRegistry.getEmptyRegistry(), builder); + PARSER.merge(input, builder); } /** @@ -798,7 +1132,7 @@ public final class TextFormat { public static void merge(final CharSequence input, final Message.Builder builder) throws ParseException { - merge(input, ExtensionRegistry.getEmptyRegistry(), builder); + PARSER.merge(input, builder); } /** @@ -810,35 +1144,9 @@ public final class TextFormat { final ExtensionRegistry extensionRegistry, final Message.Builder builder) throws IOException { - // Read the entire input to a String then parse that. - - // If StreamTokenizer were not quite so crippled, or if there were a kind - // of Reader that could read in chunks that match some particular regex, - // or if we wanted to write a custom Reader to tokenize our stream, then - // we would not have to read to one big String. Alas, none of these is - // the case. Oh well. - - merge(toStringBuilder(input), extensionRegistry, builder); + PARSER.merge(input, extensionRegistry, builder); } - private static final int BUFFER_SIZE = 4096; - - // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer) - // overhead is worthwhile - private static StringBuilder toStringBuilder(final Readable input) - throws IOException { - final StringBuilder text = new StringBuilder(); - final CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE); - while (true) { - final int n = input.read(buffer); - if (n == -1) { - break; - } - buffer.flip(); - text.append(buffer, 0, n); - } - return text; - } /** * Parse a text-format message from {@code input} and merge the contents @@ -849,187 +1157,466 @@ public final class TextFormat { final ExtensionRegistry extensionRegistry, final Message.Builder builder) throws ParseException { - final Tokenizer tokenizer = new Tokenizer(input); - - while (!tokenizer.atEnd()) { - mergeField(tokenizer, extensionRegistry, builder); - } + PARSER.merge(input, extensionRegistry, builder); } + /** - * Parse a single field from {@code tokenizer} and merge it into - * {@code builder}. + * Parser for text-format proto2 instances. This class is thread-safe. + * The implementation largely follows google/protobuf/text_format.cc. + * + *

Use {@link TextFormat#getParser()} to obtain the default parser, or + * {@link Builder} to control the parser behavior. */ - private static void mergeField(final Tokenizer tokenizer, - final ExtensionRegistry extensionRegistry, - final Message.Builder builder) - throws ParseException { - FieldDescriptor field; - final Descriptor type = builder.getDescriptorForType(); - ExtensionRegistry.ExtensionInfo extension = null; + public static class Parser { + /** + * Determines if repeated values for non-repeated fields and + * oneofs are permitted. For example, given required/optional field "foo" + * and a oneof containing "baz" and "qux": + *

  • + *
      "foo: 1 foo: 2" + *
        "baz: 1 qux: 2" + *
          merging "foo: 2" into a proto in which foo is already set, or + *
            merging "qux: 2" into a proto in which baz is already set. + * + */ + public enum SingularOverwritePolicy { + /** The last value is retained. */ + ALLOW_SINGULAR_OVERWRITES, + /** An error is issued. */ + FORBID_SINGULAR_OVERWRITES + } - if (tokenizer.tryConsume("[")) { - // An extension. - final StringBuilder name = - new StringBuilder(tokenizer.consumeIdentifier()); - while (tokenizer.tryConsume(".")) { - name.append('.'); - name.append(tokenizer.consumeIdentifier()); - } + private final boolean allowUnknownFields; + private final SingularOverwritePolicy singularOverwritePolicy; + + private Parser(boolean allowUnknownFields, + SingularOverwritePolicy singularOverwritePolicy) { + this.allowUnknownFields = allowUnknownFields; + this.singularOverwritePolicy = singularOverwritePolicy; + } + + /** + * Returns a new instance of {@link Builder}. + */ + public static Builder newBuilder() { + return new Builder(); + } - extension = extensionRegistry.findExtensionByName(name.toString()); + /** + * Builder that can be used to obtain new instances of {@link Parser}. + */ + public static class Builder { + private boolean allowUnknownFields = false; + private SingularOverwritePolicy singularOverwritePolicy = + SingularOverwritePolicy.ALLOW_SINGULAR_OVERWRITES; + + /** + * Sets parser behavior when a non-repeated field appears more than once. + */ + public Builder setSingularOverwritePolicy(SingularOverwritePolicy p) { + this.singularOverwritePolicy = p; + return this; + } - if (extension == null) { - throw tokenizer.parseExceptionPreviousToken( - "Extension \"" + name + "\" not found in the ExtensionRegistry."); - } else if (extension.descriptor.getContainingType() != type) { - throw tokenizer.parseExceptionPreviousToken( - "Extension \"" + name + "\" does not extend message type \"" + - type.getFullName() + "\"."); + public Parser build() { + return new Parser(allowUnknownFields, singularOverwritePolicy); } + } - tokenizer.consume("]"); + /** + * Parse a text-format message from {@code input} and merge the contents + * into {@code builder}. + */ + public void merge(final Readable input, + final Message.Builder builder) + throws IOException { + merge(input, ExtensionRegistry.getEmptyRegistry(), builder); + } - field = extension.descriptor; - } else { - final String name = tokenizer.consumeIdentifier(); - field = type.findFieldByName(name); + /** + * Parse a text-format message from {@code input} and merge the contents + * into {@code builder}. + */ + public void merge(final CharSequence input, + final Message.Builder builder) + throws ParseException { + merge(input, ExtensionRegistry.getEmptyRegistry(), builder); + } - // Group names are expected to be capitalized as they appear in the - // .proto file, which actually matches their type names, not their field - // names. - if (field == null) { - // Explicitly specify US locale so that this code does not break when - // executing in Turkey. - final String lowerName = name.toLowerCase(Locale.US); - field = type.findFieldByName(lowerName); - // If the case-insensitive match worked but the field is NOT a group, - if (field != null && field.getType() != FieldDescriptor.Type.GROUP) { - field = null; + /** + * Parse a text-format message from {@code input} and merge the contents + * into {@code builder}. Extensions will be recognized if they are + * registered in {@code extensionRegistry}. + */ + public void merge(final Readable input, + final ExtensionRegistry extensionRegistry, + final Message.Builder builder) + throws IOException { + // Read the entire input to a String then parse that. + + // If StreamTokenizer were not quite so crippled, or if there were a kind + // of Reader that could read in chunks that match some particular regex, + // or if we wanted to write a custom Reader to tokenize our stream, then + // we would not have to read to one big String. Alas, none of these is + // the case. Oh well. + + merge(toStringBuilder(input), extensionRegistry, builder); + } + + + private static final int BUFFER_SIZE = 4096; + + // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer) + // overhead is worthwhile + private static StringBuilder toStringBuilder(final Readable input) + throws IOException { + final StringBuilder text = new StringBuilder(); + final CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE); + while (true) { + final int n = input.read(buffer); + if (n == -1) { + break; } + buffer.flip(); + text.append(buffer, 0, n); } - // Again, special-case group names as described above. - if (field != null && field.getType() == FieldDescriptor.Type.GROUP && - !field.getMessageType().getName().equals(name)) { - field = null; - } + return text; + } - if (field == null) { - throw tokenizer.parseExceptionPreviousToken( - "Message type \"" + type.getFullName() + - "\" has no field named \"" + name + "\"."); + /** + * Parse a text-format message from {@code input} and merge the contents + * into {@code builder}. Extensions will be recognized if they are + * registered in {@code extensionRegistry}. + */ + public void merge(final CharSequence input, + final ExtensionRegistry extensionRegistry, + final Message.Builder builder) + throws ParseException { + final Tokenizer tokenizer = new Tokenizer(input); + MessageReflection.BuilderAdapter target = + new MessageReflection.BuilderAdapter(builder); + + while (!tokenizer.atEnd()) { + mergeField(tokenizer, extensionRegistry, target); } } - Object value = null; - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - tokenizer.tryConsume(":"); // optional + /** + * Parse a single field from {@code tokenizer} and merge it into + * {@code builder}. + */ + private void mergeField(final Tokenizer tokenizer, + final ExtensionRegistry extensionRegistry, + final MessageReflection.MergeTarget target) + throws ParseException { + FieldDescriptor field = null; + final Descriptor type = target.getDescriptorForType(); + ExtensionRegistry.ExtensionInfo extension = null; + + if (tokenizer.tryConsume("[")) { + // An extension. + final StringBuilder name = + new StringBuilder(tokenizer.consumeIdentifier()); + while (tokenizer.tryConsume(".")) { + name.append('.'); + name.append(tokenizer.consumeIdentifier()); + } - final String endToken; - if (tokenizer.tryConsume("<")) { - endToken = ">"; - } else { - tokenizer.consume("{"); - endToken = "}"; - } + extension = target.findExtensionByName( + extensionRegistry, name.toString()); + + if (extension == null) { + if (!allowUnknownFields) { + throw tokenizer.parseExceptionPreviousToken( + "Extension \"" + name + "\" not found in the ExtensionRegistry."); + } else { + logger.warning( + "Extension \"" + name + "\" not found in the ExtensionRegistry."); + } + } else { + if (extension.descriptor.getContainingType() != type) { + throw tokenizer.parseExceptionPreviousToken( + "Extension \"" + name + "\" does not extend message type \"" + + type.getFullName() + "\"."); + } + field = extension.descriptor; + } - final Message.Builder subBuilder; - if (extension == null) { - subBuilder = builder.newBuilderForField(field); + tokenizer.consume("]"); } else { - subBuilder = extension.defaultInstance.newBuilderForType(); - } + final String name = tokenizer.consumeIdentifier(); + field = type.findFieldByName(name); + + // Group names are expected to be capitalized as they appear in the + // .proto file, which actually matches their type names, not their field + // names. + if (field == null) { + // Explicitly specify US locale so that this code does not break when + // executing in Turkey. + final String lowerName = name.toLowerCase(Locale.US); + field = type.findFieldByName(lowerName); + // If the case-insensitive match worked but the field is NOT a group, + if (field != null && field.getType() != FieldDescriptor.Type.GROUP) { + field = null; + } + } + // Again, special-case group names as described above. + if (field != null && field.getType() == FieldDescriptor.Type.GROUP && + !field.getMessageType().getName().equals(name)) { + field = null; + } - while (!tokenizer.tryConsume(endToken)) { - if (tokenizer.atEnd()) { - throw tokenizer.parseException( - "Expected \"" + endToken + "\"."); + if (field == null) { + if (!allowUnknownFields) { + throw tokenizer.parseExceptionPreviousToken( + "Message type \"" + type.getFullName() + + "\" has no field named \"" + name + "\"."); + } else { + logger.warning( + "Message type \"" + type.getFullName() + + "\" has no field named \"" + name + "\"."); + } } - mergeField(tokenizer, extensionRegistry, subBuilder); } - value = subBuilder.build(); - - } else { - tokenizer.consume(":"); + // Skips unknown fields. + if (field == null) { + // Try to guess the type of this field. + // If this field is not a message, there should be a ":" between the + // field name and the field value and also the field value should not + // start with "{" or "<" which indicates the begining of a message body. + // If there is no ":" or there is a "{" or "<" after ":", this field has + // to be a message or the input is ill-formed. + if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("{") && + !tokenizer.lookingAt("<")) { + skipFieldValue(tokenizer); + } else { + skipFieldMessage(tokenizer); + } + return; + } - switch (field.getType()) { - case INT32: - case SINT32: - case SFIXED32: - value = tokenizer.consumeInt32(); - break; + // Handle potential ':'. + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + tokenizer.tryConsume(":"); // optional + } else { + tokenizer.consume(":"); // required + } + // Support specifying repeated field values as a comma-separated list. + // Ex."foo: [1, 2, 3]" + if (field.isRepeated() && tokenizer.tryConsume("[")) { + while (true) { + consumeFieldValue(tokenizer, extensionRegistry, target, field, extension); + if (tokenizer.tryConsume("]")) { + // End of list. + break; + } + tokenizer.consume(","); + } + } else { + consumeFieldValue(tokenizer, extensionRegistry, target, field, extension); + } + } - case INT64: - case SINT64: - case SFIXED64: - value = tokenizer.consumeInt64(); - break; + /** + * Parse a single field value from {@code tokenizer} and merge it into + * {@code builder}. + */ + private void consumeFieldValue( + final Tokenizer tokenizer, + final ExtensionRegistry extensionRegistry, + final MessageReflection.MergeTarget target, + final FieldDescriptor field, + final ExtensionRegistry.ExtensionInfo extension) + throws ParseException { + Object value = null; + + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + final String endToken; + if (tokenizer.tryConsume("<")) { + endToken = ">"; + } else { + tokenizer.consume("{"); + endToken = "}"; + } - case UINT32: - case FIXED32: - value = tokenizer.consumeUInt32(); - break; + final MessageReflection.MergeTarget subField; + subField = target.newMergeTargetForField(field, + (extension == null) ? null : extension.defaultInstance); - case UINT64: - case FIXED64: - value = tokenizer.consumeUInt64(); - break; + while (!tokenizer.tryConsume(endToken)) { + if (tokenizer.atEnd()) { + throw tokenizer.parseException( + "Expected \"" + endToken + "\"."); + } + mergeField(tokenizer, extensionRegistry, subField); + } - case FLOAT: - value = tokenizer.consumeFloat(); - break; + value = subField.finish(); - case DOUBLE: - value = tokenizer.consumeDouble(); - break; + } else { + switch (field.getType()) { + case INT32: + case SINT32: + case SFIXED32: + value = tokenizer.consumeInt32(); + break; + + case INT64: + case SINT64: + case SFIXED64: + value = tokenizer.consumeInt64(); + break; + + case UINT32: + case FIXED32: + value = tokenizer.consumeUInt32(); + break; + + case UINT64: + case FIXED64: + value = tokenizer.consumeUInt64(); + break; + + case FLOAT: + value = tokenizer.consumeFloat(); + break; + + case DOUBLE: + value = tokenizer.consumeDouble(); + break; + + case BOOL: + value = tokenizer.consumeBoolean(); + break; + + case STRING: + value = tokenizer.consumeString(); + break; + + case BYTES: + value = tokenizer.consumeByteString(); + break; + + case ENUM: + final EnumDescriptor enumType = field.getEnumType(); + + if (tokenizer.lookingAtInteger()) { + final int number = tokenizer.consumeInt32(); + value = enumType.findValueByNumber(number); + if (value == null) { + throw tokenizer.parseExceptionPreviousToken( + "Enum type \"" + enumType.getFullName() + + "\" has no value with number " + number + '.'); + } + } else { + final String id = tokenizer.consumeIdentifier(); + value = enumType.findValueByName(id); + if (value == null) { + throw tokenizer.parseExceptionPreviousToken( + "Enum type \"" + enumType.getFullName() + + "\" has no value named \"" + id + "\"."); + } + } - case BOOL: - value = tokenizer.consumeBoolean(); - break; + break; - case STRING: - value = tokenizer.consumeString(); - break; + case MESSAGE: + case GROUP: + throw new RuntimeException("Can't get here."); + } + } - case BYTES: - value = tokenizer.consumeByteString(); - break; + if (field.isRepeated()) { + target.addRepeatedField(field, value); + } else if ((singularOverwritePolicy + == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES) + && target.hasField(field)) { + throw tokenizer.parseExceptionPreviousToken("Non-repeated field \"" + + field.getFullName() + "\" cannot be overwritten."); + } else if ((singularOverwritePolicy + == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES) + && field.getContainingOneof() != null + && target.hasOneof(field.getContainingOneof())) { + Descriptors.OneofDescriptor oneof = field.getContainingOneof(); + throw tokenizer.parseExceptionPreviousToken("Field \"" + + field.getFullName() + "\" is specified along with field \"" + + target.getOneofFieldDescriptor(oneof).getFullName() + + "\", another member of oneof \"" + oneof.getName() + "\"."); + } else { + target.setField(field, value); + } + } - case ENUM: - final EnumDescriptor enumType = field.getEnumType(); - - if (tokenizer.lookingAtInteger()) { - final int number = tokenizer.consumeInt32(); - value = enumType.findValueByNumber(number); - if (value == null) { - throw tokenizer.parseExceptionPreviousToken( - "Enum type \"" + enumType.getFullName() + - "\" has no value with number " + number + '.'); - } - } else { - final String id = tokenizer.consumeIdentifier(); - value = enumType.findValueByName(id); - if (value == null) { - throw tokenizer.parseExceptionPreviousToken( - "Enum type \"" + enumType.getFullName() + - "\" has no value named \"" + id + "\"."); - } - } + /** + * Skips the next field including the field's name and value. + */ + private void skipField(Tokenizer tokenizer) throws ParseException { + if (tokenizer.tryConsume("[")) { + // Extension name. + do { + tokenizer.consumeIdentifier(); + } while (tokenizer.tryConsume(".")); + tokenizer.consume("]"); + } else { + tokenizer.consumeIdentifier(); + } - break; + // Try to guess the type of this field. + // If this field is not a message, there should be a ":" between the + // field name and the field value and also the field value should not + // start with "{" or "<" which indicates the begining of a message body. + // If there is no ":" or there is a "{" or "<" after ":", this field has + // to be a message or the input is ill-formed. + if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("<") && + !tokenizer.lookingAt("{")) { + skipFieldValue(tokenizer); + } else { + skipFieldMessage(tokenizer); + } + // For historical reasons, fields may optionally be separated by commas or + // semicolons. + if (!tokenizer.tryConsume(";")) { + tokenizer.tryConsume(","); + } + } - case MESSAGE: - case GROUP: - throw new RuntimeException("Can't get here."); + /** + * Skips the whole body of a message including the beginning delimeter and + * the ending delimeter. + */ + private void skipFieldMessage(Tokenizer tokenizer) throws ParseException { + final String delimiter; + if (tokenizer.tryConsume("<")) { + delimiter = ">"; + } else { + tokenizer.consume("{"); + delimiter = "}"; } + while (!tokenizer.lookingAt(">") && !tokenizer.lookingAt("}")) { + skipField(tokenizer); + } + tokenizer.consume(delimiter); } - if (field.isRepeated()) { - builder.addRepeatedField(field, value); - } else { - builder.setField(field, value); + /** + * Skips a field value. + */ + private void skipFieldValue(Tokenizer tokenizer) throws ParseException { + if (tokenizer.tryConsumeString()) { + while (tokenizer.tryConsumeString()) {} + return; + } + if (!tokenizer.tryConsumeIdentifier() && // includes enum & boolean + !tokenizer.tryConsumeInt64() && // includes int32 + !tokenizer.tryConsumeUInt64() && // includes uint32 + !tokenizer.tryConsumeDouble() && + !tokenizer.tryConsumeFloat()) { + throw tokenizer.parseException( + "Invalid field value: " + tokenizer.currentToken); + } } } @@ -1039,6 +1626,11 @@ public final class TextFormat { // Some of these methods are package-private because Descriptors.java uses // them. + private interface ByteSequence { + int size(); + byte byteAt(int offset); + } + /** * Escapes bytes in the format used in protocol buffer text format, which * is the same as the format used for C string literals. All bytes @@ -1047,7 +1639,7 @@ public final class TextFormat { * which no defined short-hand escape sequence is defined will be escaped * using 3-digit octal sequences. */ - static String escapeBytes(final ByteString input) { + private static String escapeBytes(final ByteSequence input) { final StringBuilder builder = new StringBuilder(input.size()); for (int i = 0; i < input.size(); i++) { final byte b = input.byteAt(i); @@ -1064,6 +1656,9 @@ public final class TextFormat { case '\'': builder.append("\\\'"); break; case '"' : builder.append("\\\""); break; default: + // Note: Bytes with the high-order bit set should be escaped. Since + // bytes are signed, such bytes will compare less than 0x20, hence + // the following line is correct. if (b >= 0x20) { builder.append((char) b); } else { @@ -1079,31 +1674,74 @@ public final class TextFormat { } /** + * Escapes bytes in the format used in protocol buffer text format, which + * is the same as the format used for C string literals. All bytes + * that are not printable 7-bit ASCII characters are escaped, as well as + * backslash, single-quote, and double-quote characters. Characters for + * which no defined short-hand escape sequence is defined will be escaped + * using 3-digit octal sequences. + */ + static String escapeBytes(final ByteString input) { + return escapeBytes(new ByteSequence() { + public int size() { + return input.size(); + } + public byte byteAt(int offset) { + return input.byteAt(offset); + } + }); + } + + /** + * Like {@link #escapeBytes(ByteString)}, but used for byte array. + */ + static String escapeBytes(final byte[] input) { + return escapeBytes(new ByteSequence() { + public int size() { + return input.length; + } + public byte byteAt(int offset) { + return input[offset]; + } + }); + } + + /** * Un-escape a byte sequence as escaped using * {@link #escapeBytes(ByteString)}. Two-digit hex escapes (starting with * "\x") are also recognized. */ - static ByteString unescapeBytes(final CharSequence input) + static ByteString unescapeBytes(final CharSequence charString) throws InvalidEscapeSequenceException { - final byte[] result = new byte[input.length()]; + // First convert the Java character sequence to UTF-8 bytes. + ByteString input = ByteString.copyFromUtf8(charString.toString()); + // Then unescape certain byte sequences introduced by ASCII '\\'. The valid + // escapes can all be expressed with ASCII characters, so it is safe to + // operate on bytes here. + // + // Unescaping the input byte array will result in a byte sequence that's no + // longer than the input. That's because each escape sequence is between + // two and four bytes long and stands for a single byte. + final byte[] result = new byte[input.size()]; int pos = 0; - for (int i = 0; i < input.length(); i++) { - char c = input.charAt(i); + for (int i = 0; i < input.size(); i++) { + byte c = input.byteAt(i); if (c == '\\') { - if (i + 1 < input.length()) { + if (i + 1 < input.size()) { ++i; - c = input.charAt(i); + c = input.byteAt(i); if (isOctal(c)) { // Octal escape. int code = digitValue(c); - if (i + 1 < input.length() && isOctal(input.charAt(i + 1))) { + if (i + 1 < input.size() && isOctal(input.byteAt(i + 1))) { ++i; - code = code * 8 + digitValue(input.charAt(i)); + code = code * 8 + digitValue(input.byteAt(i)); } - if (i + 1 < input.length() && isOctal(input.charAt(i + 1))) { + if (i + 1 < input.size() && isOctal(input.byteAt(i + 1))) { ++i; - code = code * 8 + digitValue(input.charAt(i)); + code = code * 8 + digitValue(input.byteAt(i)); } + // TODO: Check that 0 <= code && code <= 0xFF. result[pos++] = (byte)code; } else { switch (c) { @@ -1121,31 +1759,31 @@ public final class TextFormat { case 'x': // hex escape int code = 0; - if (i + 1 < input.length() && isHex(input.charAt(i + 1))) { + if (i + 1 < input.size() && isHex(input.byteAt(i + 1))) { ++i; - code = digitValue(input.charAt(i)); + code = digitValue(input.byteAt(i)); } else { throw new InvalidEscapeSequenceException( - "Invalid escape sequence: '\\x' with no digits"); + "Invalid escape sequence: '\\x' with no digits"); } - if (i + 1 < input.length() && isHex(input.charAt(i + 1))) { + if (i + 1 < input.size() && isHex(input.byteAt(i + 1))) { ++i; - code = code * 16 + digitValue(input.charAt(i)); + code = code * 16 + digitValue(input.byteAt(i)); } result[pos++] = (byte)code; break; default: throw new InvalidEscapeSequenceException( - "Invalid escape sequence: '\\" + c + '\''); + "Invalid escape sequence: '\\" + (char)c + '\''); } } } else { throw new InvalidEscapeSequenceException( - "Invalid escape sequence: '\\' at end of string."); + "Invalid escape sequence: '\\' at end of string."); } } else { - result[pos++] = (byte)c; + result[pos++] = c; } } @@ -1174,6 +1812,13 @@ public final class TextFormat { } /** + * Escape double quotes and backslashes in a String for unicode output of a message. + */ + public static String escapeDoubleQuotesAndBackslashes(final String input) { + return input.replace("\\", "\\\\").replace("\"", "\\\""); + } + + /** * Un-escape a text string as escaped using {@link #escapeText(String)}. * Two-digit hex escapes (starting with "\x") are also recognized. */ @@ -1183,12 +1828,12 @@ public final class TextFormat { } /** Is this an octal digit? */ - private static boolean isOctal(final char c) { + private static boolean isOctal(final byte c) { return '0' <= c && c <= '7'; } /** Is this a hex digit? */ - private static boolean isHex(final char c) { + private static boolean isHex(final byte c) { return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); @@ -1199,7 +1844,7 @@ public final class TextFormat { * numeric value. This is like {@code Character.digit()} but we don't accept * non-ASCII digits. */ - private static int digitValue(final char c) { + private static int digitValue(final byte c) { if ('0' <= c && c <= '9') { return c - '0'; } else if ('a' <= c && c <= 'z') { @@ -1212,7 +1857,7 @@ public final class TextFormat { /** * Parse a 32-bit signed integer from the text. Unlike the Java standard * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" - * and "0" to signify hexidecimal and octal numbers, respectively. + * and "0" to signify hexadecimal and octal numbers, respectively. */ static int parseInt32(final String text) throws NumberFormatException { return (int) parseInteger(text, true, false); @@ -1221,7 +1866,7 @@ public final class TextFormat { /** * Parse a 32-bit unsigned integer from the text. Unlike the Java standard * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" - * and "0" to signify hexidecimal and octal numbers, respectively. The + * and "0" to signify hexadecimal and octal numbers, respectively. The * result is coerced to a (signed) {@code int} when returned since Java has * no unsigned integer type. */ @@ -1232,7 +1877,7 @@ public final class TextFormat { /** * Parse a 64-bit signed integer from the text. Unlike the Java standard * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" - * and "0" to signify hexidecimal and octal numbers, respectively. + * and "0" to signify hexadecimal and octal numbers, respectively. */ static long parseInt64(final String text) throws NumberFormatException { return parseInteger(text, true, true); @@ -1241,7 +1886,7 @@ public final class TextFormat { /** * Parse a 64-bit unsigned integer from the text. Unlike the Java standard * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" - * and "0" to signify hexidecimal and octal numbers, respectively. The + * and "0" to signify hexadecimal and octal numbers, respectively. The * result is coerced to a (signed) {@code long} when returned since Java has * no unsigned long type. */ diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java index 26a15d0..81432b4 100644 --- a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java +++ b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java @@ -46,7 +46,7 @@ import java.util.TreeMap; * {@code UnknownFieldSet} is used to keep track of fields which were seen when * parsing a protocol message but whose field numbers or types are unrecognized. * This most frequently occurs when new fields are added to a message type - * and then messages containing those feilds are read by old software that was + * and then messages containing those fields are read by old software that was * compiled before the new types were added. * *

            Every {@link Message} contains an {@code UnknownFieldSet} (and every @@ -91,6 +91,7 @@ public final class UnknownFieldSet implements MessageLite { } private Map fields; + @Override public boolean equals(final Object other) { if (this == other) { @@ -367,6 +368,22 @@ public final class UnknownFieldSet implements MessageLite { reinitialize(); return this; } + + /** Clear fields from the set with a given field number. */ + public Builder clearField(final int number) { + if (number == 0) { + throw new IllegalArgumentException("Zero is not a valid field number."); + } + if (lastField != null && lastFieldNumber == number) { + // Discard this. + lastField = null; + lastFieldNumber = 0; + } + if (fields.containsKey(number)) { + fields.remove(number); + } + return this; + } /** * Merge the fields from {@code other} into this set. If a field number @@ -468,7 +485,7 @@ public final class UnknownFieldSet implements MessageLite { /** * Parse a single field from {@code input} and merge it into this set. * @param tag The field's tag number, which was already parsed. - * @return {@code false} if the tag is an engroup tag. + * @return {@code false} if the tag is an end group tag. */ public boolean mergeFieldFrom(final int tag, final CodedInputStream input) throws IOException { @@ -950,4 +967,29 @@ public final class UnknownFieldSet implements MessageLite { } } } + + /** + * Parser to implement MessageLite interface. + */ + public static final class Parser extends AbstractParser { + public UnknownFieldSet parsePartialFrom( + CodedInputStream input, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input); + } catch (InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (IOException e) { + throw new InvalidProtocolBufferException(e.getMessage()) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + } + + private static final Parser PARSER = new Parser(); + public final Parser getParserForType() { + return PARSER; + } } diff --git a/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java b/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java new file mode 100644 index 0000000..6f9905f --- /dev/null +++ b/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java @@ -0,0 +1,205 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.RandomAccess; + +/** + * An implementation of {@link LazyStringList} that wraps another + * {@link LazyStringList} such that it cannot be modified via the wrapper. + * + * @author jonp@google.com (Jon Perlow) + */ +public class UnmodifiableLazyStringList extends AbstractList + implements LazyStringList, RandomAccess { + + private final LazyStringList list; + + public UnmodifiableLazyStringList(LazyStringList list) { + this.list = list; + } + + @Override + public String get(int index) { + return list.get(index); + } + + @Override + public int size() { + return list.size(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public ByteString getByteString(int index) { + return list.getByteString(index); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void add(ByteString element) { + throw new UnsupportedOperationException(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void set(int index, ByteString element) { + throw new UnsupportedOperationException(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public boolean addAllByteString(Collection element) { + throw new UnsupportedOperationException(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public byte[] getByteArray(int index) { + return list.getByteArray(index); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void add(byte[] element) { + throw new UnsupportedOperationException(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void set(int index, byte[] element) { + throw new UnsupportedOperationException(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public boolean addAllByteArray(Collection element) { + throw new UnsupportedOperationException(); + } + + @Override + public ListIterator listIterator(final int index) { + return new ListIterator() { + ListIterator iter = list.listIterator(index); + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public boolean hasNext() { + return iter.hasNext(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public String next() { + return iter.next(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public boolean hasPrevious() { + return iter.hasPrevious(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public String previous() { + return iter.previous(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public int nextIndex() { + return iter.nextIndex(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public int previousIndex() { + return iter.previousIndex(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void remove() { + throw new UnsupportedOperationException(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void set(String o) { + throw new UnsupportedOperationException(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void add(String o) { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + public Iterator iterator() { + return new Iterator() { + Iterator iter = list.iterator(); + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public boolean hasNext() { + return iter.hasNext(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public String next() { + return iter.next(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public List getUnderlyingElements() { + // The returned value is already unmodifiable. + return list.getUnderlyingElements(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void mergeFrom(LazyStringList other) { + throw new UnsupportedOperationException(); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public List asByteArrayList() { + return Collections.unmodifiableList(list.asByteArrayList()); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public List asByteStringList() { + return Collections.unmodifiableList(list.asByteStringList()); + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public LazyStringList getUnmodifiableView() { + return this; + } +} diff --git a/java/src/main/java/com/google/protobuf/Utf8.java b/java/src/main/java/com/google/protobuf/Utf8.java new file mode 100644 index 0000000..388f7fc --- /dev/null +++ b/java/src/main/java/com/google/protobuf/Utf8.java @@ -0,0 +1,349 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +/** + * A set of low-level, high-performance static utility methods related + * to the UTF-8 character encoding. This class has no dependencies + * outside of the core JDK libraries. + * + *

            There are several variants of UTF-8. The one implemented by + * this class is the restricted definition of UTF-8 introduced in + * Unicode 3.1, which mandates the rejection of "overlong" byte + * sequences as well as rejection of 3-byte surrogate codepoint byte + * sequences. Note that the UTF-8 decoder included in Oracle's JDK + * has been modified to also reject "overlong" byte sequences, but (as + * of 2011) still accepts 3-byte surrogate codepoint byte sequences. + * + *

            The byte sequences considered valid by this class are exactly + * those that can be roundtrip converted to Strings and back to bytes + * using the UTF-8 charset, without loss:

             {@code
            + * Arrays.equals(bytes, new String(bytes, "UTF-8").getBytes("UTF-8"))
            + * }
            + * + *

            See the Unicode Standard,
            + * Table 3-6. UTF-8 Bit Distribution,
            + * Table 3-7. Well Formed UTF-8 Byte Sequences. + * + *

            This class supports decoding of partial byte sequences, so that the + * bytes in a complete UTF-8 byte sequences can be stored in multiple + * segments. Methods typically return {@link #MALFORMED} if the partial + * byte sequence is definitely not well-formed, {@link #COMPLETE} if it is + * well-formed in the absence of additional input, or if the byte sequence + * apparently terminated in the middle of a character, an opaque integer + * "state" value containing enough information to decode the character when + * passed to a subsequent invocation of a partial decoding method. + * + * @author martinrb@google.com (Martin Buchholz) + */ +final class Utf8 { + private Utf8() {} + + /** + * State value indicating that the byte sequence is well-formed and + * complete (no further bytes are needed to complete a character). + */ + public static final int COMPLETE = 0; + + /** + * State value indicating that the byte sequence is definitely not + * well-formed. + */ + public static final int MALFORMED = -1; + + // Other state values include the partial bytes of the incomplete + // character to be decoded in the simplest way: we pack the bytes + // into the state int in little-endian order. For example: + // + // int state = byte1 ^ (byte2 << 8) ^ (byte3 << 16); + // + // Such a state is unpacked thus (note the ~ operation for byte2 to + // undo byte1's sign-extension bits): + // + // int byte1 = (byte) state; + // int byte2 = (byte) ~(state >> 8); + // int byte3 = (byte) (state >> 16); + // + // We cannot store a zero byte in the state because it would be + // indistinguishable from the absence of a byte. But we don't need + // to, because partial bytes must always be negative. When building + // a state, we ensure that byte1 is negative and subsequent bytes + // are valid trailing bytes. + + /** + * Returns {@code true} if the given byte array is a well-formed + * UTF-8 byte sequence. + * + *

            This is a convenience method, equivalent to a call to {@code + * isValidUtf8(bytes, 0, bytes.length)}. + */ + public static boolean isValidUtf8(byte[] bytes) { + return isValidUtf8(bytes, 0, bytes.length); + } + + /** + * Returns {@code true} if the given byte array slice is a + * well-formed UTF-8 byte sequence. The range of bytes to be + * checked extends from index {@code index}, inclusive, to {@code + * limit}, exclusive. + * + *

            This is a convenience method, equivalent to {@code + * partialIsValidUtf8(bytes, index, limit) == Utf8.COMPLETE}. + */ + public static boolean isValidUtf8(byte[] bytes, int index, int limit) { + return partialIsValidUtf8(bytes, index, limit) == COMPLETE; + } + + /** + * Tells whether the given byte array slice is a well-formed, + * malformed, or incomplete UTF-8 byte sequence. The range of bytes + * to be checked extends from index {@code index}, inclusive, to + * {@code limit}, exclusive. + * + * @param state either {@link Utf8#COMPLETE} (if this is the initial decoding + * operation) or the value returned from a call to a partial decoding method + * for the previous bytes + * + * @return {@link #MALFORMED} if the partial byte sequence is + * definitely not well-formed, {@link #COMPLETE} if it is well-formed + * (no additional input needed), or if the byte sequence is + * "incomplete", i.e. apparently terminated in the middle of a character, + * an opaque integer "state" value containing enough information to + * decode the character when passed to a subsequent invocation of a + * partial decoding method. + */ + public static int partialIsValidUtf8( + int state, byte[] bytes, int index, int limit) { + if (state != COMPLETE) { + // The previous decoding operation was incomplete (or malformed). + // We look for a well-formed sequence consisting of bytes from + // the previous decoding operation (stored in state) together + // with bytes from the array slice. + // + // We expect such "straddler characters" to be rare. + + if (index >= limit) { // No bytes? No progress. + return state; + } + int byte1 = (byte) state; + // byte1 is never ASCII. + if (byte1 < (byte) 0xE0) { + // two-byte form + + // Simultaneously checks for illegal trailing-byte in + // leading position and overlong 2-byte form. + if (byte1 < (byte) 0xC2 || + // byte2 trailing-byte test + bytes[index++] > (byte) 0xBF) { + return MALFORMED; + } + } else if (byte1 < (byte) 0xF0) { + // three-byte form + + // Get byte2 from saved state or array + int byte2 = (byte) ~(state >> 8); + if (byte2 == 0) { + byte2 = bytes[index++]; + if (index >= limit) { + return incompleteStateFor(byte1, byte2); + } + } + if (byte2 > (byte) 0xBF || + // overlong? 5 most significant bits must not all be zero + (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0) || + // illegal surrogate codepoint? + (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0) || + // byte3 trailing-byte test + bytes[index++] > (byte) 0xBF) { + return MALFORMED; + } + } else { + // four-byte form + + // Get byte2 and byte3 from saved state or array + int byte2 = (byte) ~(state >> 8); + int byte3 = 0; + if (byte2 == 0) { + byte2 = bytes[index++]; + if (index >= limit) { + return incompleteStateFor(byte1, byte2); + } + } else { + byte3 = (byte) (state >> 16); + } + if (byte3 == 0) { + byte3 = bytes[index++]; + if (index >= limit) { + return incompleteStateFor(byte1, byte2, byte3); + } + } + + // If we were called with state == MALFORMED, then byte1 is 0xFF, + // which never occurs in well-formed UTF-8, and so we will return + // MALFORMED again below. + + if (byte2 > (byte) 0xBF || + // Check that 1 <= plane <= 16. Tricky optimized form of: + // if (byte1 > (byte) 0xF4 || + // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 || + // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F) + (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0 || + // byte3 trailing-byte test + byte3 > (byte) 0xBF || + // byte4 trailing-byte test + bytes[index++] > (byte) 0xBF) { + return MALFORMED; + } + } + } + + return partialIsValidUtf8(bytes, index, limit); + } + + /** + * Tells whether the given byte array slice is a well-formed, + * malformed, or incomplete UTF-8 byte sequence. The range of bytes + * to be checked extends from index {@code index}, inclusive, to + * {@code limit}, exclusive. + * + *

            This is a convenience method, equivalent to a call to {@code + * partialIsValidUtf8(Utf8.COMPLETE, bytes, index, limit)}. + * + * @return {@link #MALFORMED} if the partial byte sequence is + * definitely not well-formed, {@link #COMPLETE} if it is well-formed + * (no additional input needed), or if the byte sequence is + * "incomplete", i.e. apparently terminated in the middle of a character, + * an opaque integer "state" value containing enough information to + * decode the character when passed to a subsequent invocation of a + * partial decoding method. + */ + public static int partialIsValidUtf8( + byte[] bytes, int index, int limit) { + // Optimize for 100% ASCII. + // Hotspot loves small simple top-level loops like this. + while (index < limit && bytes[index] >= 0) { + index++; + } + + return (index >= limit) ? COMPLETE : + partialIsValidUtf8NonAscii(bytes, index, limit); + } + + private static int partialIsValidUtf8NonAscii( + byte[] bytes, int index, int limit) { + for (;;) { + int byte1, byte2; + + // Optimize for interior runs of ASCII bytes. + do { + if (index >= limit) { + return COMPLETE; + } + } while ((byte1 = bytes[index++]) >= 0); + + if (byte1 < (byte) 0xE0) { + // two-byte form + + if (index >= limit) { + return byte1; + } + + // Simultaneously checks for illegal trailing-byte in + // leading position and overlong 2-byte form. + if (byte1 < (byte) 0xC2 || + bytes[index++] > (byte) 0xBF) { + return MALFORMED; + } + } else if (byte1 < (byte) 0xF0) { + // three-byte form + + if (index >= limit - 1) { // incomplete sequence + return incompleteStateFor(bytes, index, limit); + } + if ((byte2 = bytes[index++]) > (byte) 0xBF || + // overlong? 5 most significant bits must not all be zero + (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0) || + // check for illegal surrogate codepoints + (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0) || + // byte3 trailing-byte test + bytes[index++] > (byte) 0xBF) { + return MALFORMED; + } + } else { + // four-byte form + + if (index >= limit - 2) { // incomplete sequence + return incompleteStateFor(bytes, index, limit); + } + if ((byte2 = bytes[index++]) > (byte) 0xBF || + // Check that 1 <= plane <= 16. Tricky optimized form of: + // if (byte1 > (byte) 0xF4 || + // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 || + // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F) + (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0 || + // byte3 trailing-byte test + bytes[index++] > (byte) 0xBF || + // byte4 trailing-byte test + bytes[index++] > (byte) 0xBF) { + return MALFORMED; + } + } + } + } + + private static int incompleteStateFor(int byte1) { + return (byte1 > (byte) 0xF4) ? + MALFORMED : byte1; + } + + private static int incompleteStateFor(int byte1, int byte2) { + return (byte1 > (byte) 0xF4 || + byte2 > (byte) 0xBF) ? + MALFORMED : byte1 ^ (byte2 << 8); + } + + private static int incompleteStateFor(int byte1, int byte2, int byte3) { + return (byte1 > (byte) 0xF4 || + byte2 > (byte) 0xBF || + byte3 > (byte) 0xBF) ? + MALFORMED : byte1 ^ (byte2 << 8) ^ (byte3 << 16); + } + + private static int incompleteStateFor(byte[] bytes, int index, int limit) { + int byte1 = bytes[index - 1]; + switch (limit - index) { + case 0: return incompleteStateFor(byte1); + case 1: return incompleteStateFor(byte1, bytes[index]); + case 2: return incompleteStateFor(byte1, bytes[index], bytes[index + 1]); + default: throw new AssertionError(); + } + } +} diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java index c46f7b0..dd2d631 100644 --- a/java/src/main/java/com/google/protobuf/WireFormat.java +++ b/java/src/main/java/com/google/protobuf/WireFormat.java @@ -45,12 +45,12 @@ public final class WireFormat { // Do not allow instantiation. private WireFormat() {} - static final int WIRETYPE_VARINT = 0; - static final int WIRETYPE_FIXED64 = 1; - static final int WIRETYPE_LENGTH_DELIMITED = 2; - static final int WIRETYPE_START_GROUP = 3; - static final int WIRETYPE_END_GROUP = 4; - static final int WIRETYPE_FIXED32 = 5; + public static final int WIRETYPE_VARINT = 0; + public static final int WIRETYPE_FIXED64 = 1; + public static final int WIRETYPE_LENGTH_DELIMITED = 2; + public static final int WIRETYPE_START_GROUP = 3; + public static final int WIRETYPE_END_GROUP = 4; + public static final int WIRETYPE_FIXED32 = 5; static final int TAG_TYPE_BITS = 3; static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1; @@ -146,7 +146,7 @@ public final class WireFormat { public boolean isPackable() { return true; } } - // Field numbers for feilds in MessageSet wire format. + // Field numbers for fields in MessageSet wire format. static final int MESSAGE_SET_ITEM = 1; static final int MESSAGE_SET_TYPE_ID = 2; static final int MESSAGE_SET_MESSAGE = 3; diff --git a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java index c44d660..fcbf019 100644 --- a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java +++ b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java @@ -30,6 +30,7 @@ package com.google.protobuf; +import com.google.protobuf.Descriptors.FieldDescriptor; import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize; import protobuf_unittest.UnittestProto; import protobuf_unittest.UnittestProto.ForeignMessage; @@ -167,6 +168,13 @@ public class AbstractMessageTest extends TestCase { wrappedBuilder.setUnknownFields(unknownFields); return this; } + @Override + public Message.Builder getFieldBuilder(FieldDescriptor field) { + return wrappedBuilder.getFieldBuilder(field); + } + } + public Parser getParserForType() { + return wrappedMessage.getParserForType(); } } @@ -220,6 +228,34 @@ public class AbstractMessageTest extends TestCase { TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage); } + public void testParsingUninitialized() throws Exception { + TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder(); + builder.getOptionalMessageBuilder().setDummy2(10); + ByteString bytes = builder.buildPartial().toByteString(); + Message.Builder abstractMessageBuilder = + new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder()); + // mergeFrom() should not throw initialization error. + abstractMessageBuilder.mergeFrom(bytes).buildPartial(); + try { + abstractMessageBuilder.mergeFrom(bytes).build(); + fail(); + } catch (UninitializedMessageException ex) { + // pass + } + + // test DynamicMessage directly. + Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder( + TestRequiredForeign.getDescriptor()); + // mergeFrom() should not throw initialization error. + dynamicMessageBuilder.mergeFrom(bytes).buildPartial(); + try { + dynamicMessageBuilder.mergeFrom(bytes).build(); + fail(); + } catch (UninitializedMessageException ex) { + // pass + } + } + public void testPackedSerialization() throws Exception { Message abstractMessage = new AbstractMessageWrapper(TestUtil.getPackedSet()); @@ -298,12 +334,16 @@ public class AbstractMessageTest extends TestCase { new AbstractMessageWrapper.Builder(builder); assertFalse(abstractBuilder.isInitialized()); + assertEquals("a, b, c", abstractBuilder.getInitializationErrorString()); builder.setA(1); assertFalse(abstractBuilder.isInitialized()); + assertEquals("b, c", abstractBuilder.getInitializationErrorString()); builder.setB(1); assertFalse(abstractBuilder.isInitialized()); + assertEquals("c", abstractBuilder.getInitializationErrorString()); builder.setC(1); assertTrue(abstractBuilder.isInitialized()); + assertEquals("", abstractBuilder.getInitializationErrorString()); } public void testForeignIsInitialized() throws Exception { @@ -312,18 +352,27 @@ public class AbstractMessageTest extends TestCase { new AbstractMessageWrapper.Builder(builder); assertTrue(abstractBuilder.isInitialized()); + assertEquals("", abstractBuilder.getInitializationErrorString()); builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED); assertFalse(abstractBuilder.isInitialized()); + assertEquals( + "optional_message.a, optional_message.b, optional_message.c", + abstractBuilder.getInitializationErrorString()); builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED); assertTrue(abstractBuilder.isInitialized()); + assertEquals("", abstractBuilder.getInitializationErrorString()); builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED); assertFalse(abstractBuilder.isInitialized()); + assertEquals( + "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c", + abstractBuilder.getInitializationErrorString()); builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED); assertTrue(abstractBuilder.isInitialized()); + assertEquals("", abstractBuilder.getInitializationErrorString()); } // ----------------------------------------------------------------- @@ -366,7 +415,7 @@ public class AbstractMessageTest extends TestCase { // ----------------------------------------------------------------- // Tests for equals and hashCode - + public void testEqualsAndHashCode() throws Exception { TestAllTypes a = TestUtil.getAllSet(); TestAllTypes b = TestAllTypes.newBuilder().build(); @@ -382,7 +431,7 @@ public class AbstractMessageTest extends TestCase { checkEqualsIsConsistent(d); checkEqualsIsConsistent(e); checkEqualsIsConsistent(f); - + checkNotEqual(a, b); checkNotEqual(a, c); checkNotEqual(a, d); @@ -413,19 +462,20 @@ public class AbstractMessageTest extends TestCase { checkEqualsIsConsistent(eUnknownFields); checkEqualsIsConsistent(fUnknownFields); - // Subseqent reconstitutions should be identical + // Subsequent reconstitutions should be identical UnittestProto.TestEmptyMessage eUnknownFields2 = UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray()); checkEqualsIsConsistent(eUnknownFields, eUnknownFields2); } - + + /** - * Asserts that the given proto has symetric equals and hashCode methods. + * Asserts that the given proto has symmetric equals and hashCode methods. */ private void checkEqualsIsConsistent(Message message) { // Object should be equal to itself. assertEquals(message, message); - + // Object should be equal to a dynamic copy of itself. DynamicMessage dynamic = DynamicMessage.newBuilder(message).build(); checkEqualsIsConsistent(message, dynamic); @@ -442,7 +492,7 @@ public class AbstractMessageTest extends TestCase { /** * Asserts that the given protos are not equal and have different hash codes. - * + * * @warning It's valid for non-equal objects to have the same hash code, so * this test is stricter than it needs to be. However, this should happen * relatively rarely. @@ -456,4 +506,22 @@ public class AbstractMessageTest extends TestCase { String.format("%s should have a different hash code from %s", m1, m2), m1.hashCode() == m2.hashCode()); } + + public void testCheckByteStringIsUtf8OnUtf8() { + ByteString byteString = ByteString.copyFromUtf8("some text"); + AbstractMessageLite.checkByteStringIsUtf8(byteString); + // No exception thrown. + } + + public void testCheckByteStringIsUtf8OnNonUtf8() { + ByteString byteString = + ByteString.copyFrom(new byte[]{(byte) 0x80}); // A lone continuation byte. + try { + AbstractMessageLite.checkByteStringIsUtf8(byteString); + fail("Expected AbstractMessageLite.checkByteStringIsUtf8 to throw IllegalArgumentException"); + } catch (IllegalArgumentException exception) { + assertEquals("Byte string is not UTF-8.", exception.getMessage()); + } + } + } diff --git a/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java b/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java new file mode 100644 index 0000000..20fa2df --- /dev/null +++ b/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java @@ -0,0 +1,68 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.io.UnsupportedEncodingException; + +/** + * This class tests {@link BoundedByteString}, which extends {@link LiteralByteString}, + * by inheriting the tests from {@link LiteralByteStringTest}. The only method which + * is strange enough that it needs to be overridden here is {@link #testToString()}. + * + * @author carlanton@google.com (Carl Haverl) + */ +public class BoundedByteStringTest extends LiteralByteStringTest { + + @Override + protected void setUp() throws Exception { + classUnderTest = "BoundedByteString"; + byte[] sourceBytes = ByteStringTest.getTestBytes(2341, 11337766L); + int from = 100; + int to = sourceBytes.length - 100; + stringUnderTest = ByteString.copyFrom(sourceBytes).substring(from, to); + referenceBytes = new byte[to - from]; + System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from); + expectedHashCode = 727575887; + } + + @Override + public void testToString() throws UnsupportedEncodingException { + String testString = "I love unicode \u1234\u5678 characters"; + LiteralByteString unicode = new LiteralByteString(testString.getBytes(UTF_8)); + ByteString chopped = unicode.substring(2, unicode.size() - 6); + assertEquals(classUnderTest + ".substring() must have the expected type", + classUnderTest, getActualClassName(chopped)); + + String roundTripString = chopped.toString(UTF_8); + assertEquals(classUnderTest + " unicode bytes must match", + testString.substring(2, testString.length() - 6), roundTripString); + } +} diff --git a/java/src/test/java/com/google/protobuf/ByteStringTest.java b/java/src/test/java/com/google/protobuf/ByteStringTest.java new file mode 100644 index 0000000..88d7e77 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/ByteStringTest.java @@ -0,0 +1,759 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import com.google.protobuf.ByteString.Output; + +import junit.framework.TestCase; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Random; + +/** + * Test methods with implementations in {@link ByteString}, plus do some top-level "integration" + * tests. + * + * @author carlanton@google.com (Carl Haverl) + */ +public class ByteStringTest extends TestCase { + + private static final String UTF_16 = "UTF-16"; + + static byte[] getTestBytes(int size, long seed) { + Random random = new Random(seed); + byte[] result = new byte[size]; + random.nextBytes(result); + return result; + } + + private byte[] getTestBytes(int size) { + return getTestBytes(size, 445566L); + } + + private byte[] getTestBytes() { + return getTestBytes(1000); + } + + // Compare the entire left array with a subset of the right array. + private boolean isArrayRange(byte[] left, byte[] right, int rightOffset, int length) { + boolean stillEqual = (left.length == length); + for (int i = 0; (stillEqual && i < length); ++i) { + stillEqual = (left[i] == right[rightOffset + i]); + } + return stillEqual; + } + + // Returns true only if the given two arrays have identical contents. + private boolean isArray(byte[] left, byte[] right) { + return left.length == right.length && isArrayRange(left, right, 0, left.length); + } + + public void testSubstring_BeginIndex() { + byte[] bytes = getTestBytes(); + ByteString substring = ByteString.copyFrom(bytes).substring(500); + assertTrue("substring must contain the tail of the string", + isArrayRange(substring.toByteArray(), bytes, 500, bytes.length - 500)); + } + + public void testCopyFrom_BytesOffsetSize() { + byte[] bytes = getTestBytes(); + ByteString byteString = ByteString.copyFrom(bytes, 500, 200); + assertTrue("copyFrom sub-range must contain the expected bytes", + isArrayRange(byteString.toByteArray(), bytes, 500, 200)); + } + + public void testCopyFrom_Bytes() { + byte[] bytes = getTestBytes(); + ByteString byteString = ByteString.copyFrom(bytes); + assertTrue("copyFrom must contain the expected bytes", + isArray(byteString.toByteArray(), bytes)); + } + + public void testCopyFrom_ByteBufferSize() { + byte[] bytes = getTestBytes(); + ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length); + byteBuffer.put(bytes); + byteBuffer.position(500); + ByteString byteString = ByteString.copyFrom(byteBuffer, 200); + assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes", + isArrayRange(byteString.toByteArray(), bytes, 500, 200)); + } + + public void testCopyFrom_ByteBuffer() { + byte[] bytes = getTestBytes(); + ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length); + byteBuffer.put(bytes); + byteBuffer.position(500); + ByteString byteString = ByteString.copyFrom(byteBuffer); + assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes", + isArrayRange(byteString.toByteArray(), bytes, 500, bytes.length - 500)); + } + + public void testCopyFrom_StringEncoding() throws UnsupportedEncodingException { + String testString = "I love unicode \u1234\u5678 characters"; + ByteString byteString = ByteString.copyFrom(testString, UTF_16); + byte[] testBytes = testString.getBytes(UTF_16); + assertTrue("copyFrom string must respect the charset", + isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length)); + } + + public void testCopyFrom_Utf8() throws UnsupportedEncodingException { + String testString = "I love unicode \u1234\u5678 characters"; + ByteString byteString = ByteString.copyFromUtf8(testString); + byte[] testBytes = testString.getBytes("UTF-8"); + assertTrue("copyFromUtf8 string must respect the charset", + isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length)); + } + + public void testCopyFrom_Iterable() { + byte[] testBytes = getTestBytes(77777, 113344L); + final List pieces = makeConcretePieces(testBytes); + // Call copyFrom() on a Collection + ByteString byteString = ByteString.copyFrom(pieces); + assertTrue("copyFrom a List must contain the expected bytes", + isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length)); + // Call copyFrom on an iteration that's not a collection + ByteString byteStringAlt = ByteString.copyFrom(new Iterable() { + public Iterator iterator() { + return pieces.iterator(); + } + }); + assertEquals("copyFrom from an Iteration must contain the expected bytes", + byteString, byteStringAlt); + } + + public void testCopyTo_TargetOffset() { + byte[] bytes = getTestBytes(); + ByteString byteString = ByteString.copyFrom(bytes); + byte[] target = new byte[bytes.length + 1000]; + byteString.copyTo(target, 400); + assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes", + isArrayRange(bytes, target, 400, bytes.length)); + } + + public void testReadFrom_emptyStream() throws IOException { + ByteString byteString = + ByteString.readFrom(new ByteArrayInputStream(new byte[0])); + assertSame("reading an empty stream must result in the EMPTY constant " + + "byte string", ByteString.EMPTY, byteString); + } + + public void testReadFrom_smallStream() throws IOException { + assertReadFrom(getTestBytes(10)); + } + + public void testReadFrom_mutating() throws IOException { + byte[] capturedArray = null; + EvilInputStream eis = new EvilInputStream(); + ByteString byteString = ByteString.readFrom(eis); + + capturedArray = eis.capturedArray; + byte[] originalValue = byteString.toByteArray(); + for (int x = 0; x < capturedArray.length; ++x) { + capturedArray[x] = (byte) 0; + } + + byte[] newValue = byteString.toByteArray(); + assertTrue("copyFrom byteBuffer must not grant access to underlying array", + Arrays.equals(originalValue, newValue)); + } + + // Tests sizes that are near the rope copy-out threshold. + public void testReadFrom_mediumStream() throws IOException { + assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE - 1)); + assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE)); + assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE + 1)); + assertReadFrom(getTestBytes(200)); + } + + // Tests sizes that are over multi-segment rope threshold. + public void testReadFrom_largeStream() throws IOException { + assertReadFrom(getTestBytes(0x100)); + assertReadFrom(getTestBytes(0x101)); + assertReadFrom(getTestBytes(0x110)); + assertReadFrom(getTestBytes(0x1000)); + assertReadFrom(getTestBytes(0x1001)); + assertReadFrom(getTestBytes(0x1010)); + assertReadFrom(getTestBytes(0x10000)); + assertReadFrom(getTestBytes(0x10001)); + assertReadFrom(getTestBytes(0x10010)); + } + + // Tests sizes that are near the read buffer size. + public void testReadFrom_byteBoundaries() throws IOException { + final int min = ByteString.MIN_READ_FROM_CHUNK_SIZE; + final int max = ByteString.MAX_READ_FROM_CHUNK_SIZE; + + assertReadFrom(getTestBytes(min - 1)); + assertReadFrom(getTestBytes(min)); + assertReadFrom(getTestBytes(min + 1)); + + assertReadFrom(getTestBytes(min * 2 - 1)); + assertReadFrom(getTestBytes(min * 2)); + assertReadFrom(getTestBytes(min * 2 + 1)); + + assertReadFrom(getTestBytes(min * 4 - 1)); + assertReadFrom(getTestBytes(min * 4)); + assertReadFrom(getTestBytes(min * 4 + 1)); + + assertReadFrom(getTestBytes(min * 8 - 1)); + assertReadFrom(getTestBytes(min * 8)); + assertReadFrom(getTestBytes(min * 8 + 1)); + + assertReadFrom(getTestBytes(max - 1)); + assertReadFrom(getTestBytes(max)); + assertReadFrom(getTestBytes(max + 1)); + + assertReadFrom(getTestBytes(max * 2 - 1)); + assertReadFrom(getTestBytes(max * 2)); + assertReadFrom(getTestBytes(max * 2 + 1)); + } + + // Tests that IOExceptions propagate through ByteString.readFrom(). + public void testReadFrom_IOExceptions() { + try { + ByteString.readFrom(new FailStream()); + fail("readFrom must throw the underlying IOException"); + + } catch (IOException e) { + assertEquals("readFrom must throw the expected exception", + "synthetic failure", e.getMessage()); + } + } + + // Tests that ByteString.readFrom works with streams that don't + // always fill their buffers. + public void testReadFrom_reluctantStream() throws IOException { + final byte[] data = getTestBytes(0x1000); + + ByteString byteString = ByteString.readFrom(new ReluctantStream(data)); + assertTrue("readFrom byte stream must contain the expected bytes", + isArray(byteString.toByteArray(), data)); + + // Same test as above, but with some specific chunk sizes. + assertReadFromReluctantStream(data, 100); + assertReadFromReluctantStream(data, 248); + assertReadFromReluctantStream(data, 249); + assertReadFromReluctantStream(data, 250); + assertReadFromReluctantStream(data, 251); + assertReadFromReluctantStream(data, 0x1000); + assertReadFromReluctantStream(data, 0x1001); + } + + // Fails unless ByteString.readFrom reads the bytes correctly from a + // reluctant stream with the given chunkSize parameter. + private void assertReadFromReluctantStream(byte[] bytes, int chunkSize) + throws IOException { + ByteString b = ByteString.readFrom(new ReluctantStream(bytes), chunkSize); + assertTrue("readFrom byte stream must contain the expected bytes", + isArray(b.toByteArray(), bytes)); + } + + // Tests that ByteString.readFrom works with streams that implement + // available(). + public void testReadFrom_available() throws IOException { + final byte[] data = getTestBytes(0x1001); + + ByteString byteString = ByteString.readFrom(new AvailableStream(data)); + assertTrue("readFrom byte stream must contain the expected bytes", + isArray(byteString.toByteArray(), data)); + } + + // Fails unless ByteString.readFrom reads the bytes correctly. + private void assertReadFrom(byte[] bytes) throws IOException { + ByteString byteString = + ByteString.readFrom(new ByteArrayInputStream(bytes)); + assertTrue("readFrom byte stream must contain the expected bytes", + isArray(byteString.toByteArray(), bytes)); + } + + // A stream that fails when read. + private static final class FailStream extends InputStream { + @Override public int read() throws IOException { + throw new IOException("synthetic failure"); + } + } + + // A stream that simulates blocking by only producing 250 characters + // per call to read(byte[]). + private static class ReluctantStream extends InputStream { + protected final byte[] data; + protected int pos = 0; + + public ReluctantStream(byte[] data) { + this.data = data; + } + + @Override public int read() { + if (pos == data.length) { + return -1; + } else { + return data[pos++]; + } + } + + @Override public int read(byte[] buf) { + return read(buf, 0, buf.length); + } + + @Override public int read(byte[] buf, int offset, int size) { + if (pos == data.length) { + return -1; + } + int count = Math.min(Math.min(size, data.length - pos), 250); + System.arraycopy(data, pos, buf, offset, count); + pos += count; + return count; + } + } + + // Same as above, but also implements available(). + private static final class AvailableStream extends ReluctantStream { + public AvailableStream(byte[] data) { + super(data); + } + + @Override public int available() { + return Math.min(250, data.length - pos); + } + } + + // A stream which exposes the byte array passed into read(byte[], int, int). + private static class EvilInputStream extends InputStream { + public byte[] capturedArray = null; + + @Override + public int read(byte[] buf, int off, int len) { + if (capturedArray != null) { + return -1; + } else { + capturedArray = buf; + for (int x = 0; x < len; ++x) { + buf[x] = (byte) x; + } + return len; + } + } + + @Override + public int read() { + // Purposefully do nothing. + return -1; + } + } + + // A stream which exposes the byte array passed into write(byte[], int, int). + private static class EvilOutputStream extends OutputStream { + public byte[] capturedArray = null; + + @Override + public void write(byte[] buf, int off, int len) { + if (capturedArray == null) { + capturedArray = buf; + } + } + + @Override + public void write(int ignored) { + // Purposefully do nothing. + } + } + + public void testToStringUtf8() throws UnsupportedEncodingException { + String testString = "I love unicode \u1234\u5678 characters"; + byte[] testBytes = testString.getBytes("UTF-8"); + ByteString byteString = ByteString.copyFrom(testBytes); + assertEquals("copyToStringUtf8 must respect the charset", + testString, byteString.toStringUtf8()); + } + + public void testNewOutput_InitialCapacity() throws IOException { + byte[] bytes = getTestBytes(); + ByteString.Output output = ByteString.newOutput(bytes.length + 100); + output.write(bytes); + ByteString byteString = output.toByteString(); + assertTrue( + "String built from newOutput(int) must contain the expected bytes", + isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length)); + } + + // Test newOutput() using a variety of buffer sizes and a variety of (fixed) + // write sizes + public void testNewOutput_ArrayWrite() throws IOException { + byte[] bytes = getTestBytes(); + int length = bytes.length; + int[] bufferSizes = {128, 256, length / 2, length - 1, length, length + 1, + 2 * length, 3 * length}; + int[] writeSizes = {1, 4, 5, 7, 23, bytes.length}; + + for (int bufferSize : bufferSizes) { + for (int writeSize : writeSizes) { + // Test writing the entire output writeSize bytes at a time. + ByteString.Output output = ByteString.newOutput(bufferSize); + for (int i = 0; i < length; i += writeSize) { + output.write(bytes, i, Math.min(writeSize, length - i)); + } + ByteString byteString = output.toByteString(); + assertTrue("String built from newOutput() must contain the expected bytes", + isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length)); + } + } + } + + // Test newOutput() using a variety of buffer sizes, but writing all the + // characters using write(byte); + public void testNewOutput_WriteChar() throws IOException { + byte[] bytes = getTestBytes(); + int length = bytes.length; + int[] bufferSizes = {0, 1, 128, 256, length / 2, + length - 1, length, length + 1, + 2 * length, 3 * length}; + for (int bufferSize : bufferSizes) { + ByteString.Output output = ByteString.newOutput(bufferSize); + for (byte byteValue : bytes) { + output.write(byteValue); + } + ByteString byteString = output.toByteString(); + assertTrue("String built from newOutput() must contain the expected bytes", + isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length)); + } + } + + // Test newOutput() in which we write the bytes using a variety of methods + // and sizes, and in which we repeatedly call toByteString() in the middle. + public void testNewOutput_Mixed() throws IOException { + Random rng = new Random(1); + byte[] bytes = getTestBytes(); + int length = bytes.length; + int[] bufferSizes = {0, 1, 128, 256, length / 2, + length - 1, length, length + 1, + 2 * length, 3 * length}; + + for (int bufferSize : bufferSizes) { + // Test writing the entire output using a mixture of write sizes and + // methods; + ByteString.Output output = ByteString.newOutput(bufferSize); + int position = 0; + while (position < bytes.length) { + if (rng.nextBoolean()) { + int count = 1 + rng.nextInt(bytes.length - position); + output.write(bytes, position, count); + position += count; + } else { + output.write(bytes[position]); + position++; + } + assertEquals("size() returns the right value", position, output.size()); + assertTrue("newOutput() substring must have correct bytes", + isArrayRange(output.toByteString().toByteArray(), + bytes, 0, position)); + } + ByteString byteString = output.toByteString(); + assertTrue("String built from newOutput() must contain the expected bytes", + isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length)); + } + } + + public void testNewOutputEmpty() throws IOException { + // Make sure newOutput() correctly builds empty byte strings + ByteString byteString = ByteString.newOutput().toByteString(); + assertEquals(ByteString.EMPTY, byteString); + } + + public void testNewOutput_Mutating() throws IOException { + Output os = ByteString.newOutput(5); + os.write(new byte[] {1, 2, 3, 4, 5}); + EvilOutputStream eos = new EvilOutputStream(); + os.writeTo(eos); + byte[] capturedArray = eos.capturedArray; + ByteString byteString = os.toByteString(); + byte[] oldValue = byteString.toByteArray(); + Arrays.fill(capturedArray, (byte) 0); + byte[] newValue = byteString.toByteArray(); + assertTrue("Output must not provide access to the underlying byte array", + Arrays.equals(oldValue, newValue)); + } + + public void testNewCodedBuilder() throws IOException { + byte[] bytes = getTestBytes(); + ByteString.CodedBuilder builder = ByteString.newCodedBuilder(bytes.length); + builder.getCodedOutput().writeRawBytes(bytes); + ByteString byteString = builder.build(); + assertTrue("String built from newCodedBuilder() must contain the expected bytes", + isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length)); + } + + public void testSubstringParity() { + byte[] bigBytes = getTestBytes(2048 * 1024, 113344L); + int start = 512 * 1024 - 3333; + int end = 512 * 1024 + 7777; + ByteString concreteSubstring = ByteString.copyFrom(bigBytes).substring(start, end); + boolean ok = true; + for (int i = start; ok && i < end; ++i) { + ok = (bigBytes[i] == concreteSubstring.byteAt(i - start)); + } + assertTrue("Concrete substring didn't capture the right bytes", ok); + + ByteString literalString = ByteString.copyFrom(bigBytes, start, end - start); + assertTrue("Substring must be equal to literal string", + concreteSubstring.equals(literalString)); + assertEquals("Substring must have same hashcode as literal string", + literalString.hashCode(), concreteSubstring.hashCode()); + } + + public void testCompositeSubstring() { + byte[] referenceBytes = getTestBytes(77748, 113344L); + + List pieces = makeConcretePieces(referenceBytes); + ByteString listString = ByteString.copyFrom(pieces); + + int from = 1000; + int to = 40000; + ByteString compositeSubstring = listString.substring(from, to); + byte[] substringBytes = compositeSubstring.toByteArray(); + boolean stillEqual = true; + for (int i = 0; stillEqual && i < to - from; ++i) { + stillEqual = referenceBytes[from + i] == substringBytes[i]; + } + assertTrue("Substring must return correct bytes", stillEqual); + + stillEqual = true; + for (int i = 0; stillEqual && i < to - from; ++i) { + stillEqual = referenceBytes[from + i] == compositeSubstring.byteAt(i); + } + assertTrue("Substring must support byteAt() correctly", stillEqual); + + ByteString literalSubstring = ByteString.copyFrom(referenceBytes, from, to - from); + assertTrue("Composite substring must equal a literal substring over the same bytes", + compositeSubstring.equals(literalSubstring)); + assertTrue("Literal substring must equal a composite substring over the same bytes", + literalSubstring.equals(compositeSubstring)); + + assertEquals("We must get the same hashcodes for composite and literal substrings", + literalSubstring.hashCode(), compositeSubstring.hashCode()); + + assertFalse("We can't be equal to a proper substring", + compositeSubstring.equals(literalSubstring.substring(0, literalSubstring.size() - 1))); + } + + public void testCopyFromList() { + byte[] referenceBytes = getTestBytes(77748, 113344L); + ByteString literalString = ByteString.copyFrom(referenceBytes); + + List pieces = makeConcretePieces(referenceBytes); + ByteString listString = ByteString.copyFrom(pieces); + + assertTrue("Composite string must be equal to literal string", + listString.equals(literalString)); + assertEquals("Composite string must have same hashcode as literal string", + literalString.hashCode(), listString.hashCode()); + } + + public void testConcat() { + byte[] referenceBytes = getTestBytes(77748, 113344L); + ByteString literalString = ByteString.copyFrom(referenceBytes); + + List pieces = makeConcretePieces(referenceBytes); + + Iterator iter = pieces.iterator(); + ByteString concatenatedString = iter.next(); + while (iter.hasNext()) { + concatenatedString = concatenatedString.concat(iter.next()); + } + + assertTrue("Concatenated string must be equal to literal string", + concatenatedString.equals(literalString)); + assertEquals("Concatenated string must have same hashcode as literal string", + literalString.hashCode(), concatenatedString.hashCode()); + } + + /** + * Test the Rope implementation can deal with Empty nodes, even though we + * guard against them. See also {@link LiteralByteStringTest#testConcat_empty()}. + */ + public void testConcat_empty() { + byte[] referenceBytes = getTestBytes(7748, 113344L); + ByteString literalString = ByteString.copyFrom(referenceBytes); + + ByteString duo = RopeByteString.newInstanceForTest(literalString, literalString); + ByteString temp = RopeByteString.newInstanceForTest( + RopeByteString.newInstanceForTest(literalString, ByteString.EMPTY), + RopeByteString.newInstanceForTest(ByteString.EMPTY, literalString)); + ByteString quintet = RopeByteString.newInstanceForTest(temp, ByteString.EMPTY); + + assertTrue("String with concatenated nulls must equal simple concatenate", + duo.equals(quintet)); + assertEquals("String with concatenated nulls have same hashcode as simple concatenate", + duo.hashCode(), quintet.hashCode()); + + ByteString.ByteIterator duoIter = duo.iterator(); + ByteString.ByteIterator quintetIter = quintet.iterator(); + boolean stillEqual = true; + while (stillEqual && quintetIter.hasNext()) { + stillEqual = (duoIter.nextByte() == quintetIter.nextByte()); + } + assertTrue("We must get the same characters by iterating", stillEqual); + assertFalse("Iterator must be exhausted", duoIter.hasNext()); + try { + duoIter.nextByte(); + fail("Should have thrown an exception."); + } catch (NoSuchElementException e) { + // This is success + } + try { + quintetIter.nextByte(); + fail("Should have thrown an exception."); + } catch (NoSuchElementException e) { + // This is success + } + + // Test that even if we force empty strings in as rope leaves in this + // configuration, we always get a (possibly Bounded) LiteralByteString + // for a length 1 substring. + // + // It is possible, using the testing factory method to create deeply nested + // trees of empty leaves, to make a string that will fail this test. + for (int i = 1; i < duo.size(); ++i) { + assertTrue("Substrings of size() < 2 must not be RopeByteStrings", + duo.substring(i - 1, i) instanceof LiteralByteString); + } + for (int i = 1; i < quintet.size(); ++i) { + assertTrue("Substrings of size() < 2 must not be RopeByteStrings", + quintet.substring(i - 1, i) instanceof LiteralByteString); + } + } + + public void testStartsWith() { + byte[] bytes = getTestBytes(1000, 1234L); + ByteString string = ByteString.copyFrom(bytes); + ByteString prefix = ByteString.copyFrom(bytes, 0, 500); + ByteString suffix = ByteString.copyFrom(bytes, 400, 600); + assertTrue(string.startsWith(ByteString.EMPTY)); + assertTrue(string.startsWith(string)); + assertTrue(string.startsWith(prefix)); + assertFalse(string.startsWith(suffix)); + assertFalse(prefix.startsWith(suffix)); + assertFalse(suffix.startsWith(prefix)); + assertFalse(ByteString.EMPTY.startsWith(prefix)); + assertTrue(ByteString.EMPTY.startsWith(ByteString.EMPTY)); + } + + public void testEndsWith() { + byte[] bytes = getTestBytes(1000, 1234L); + ByteString string = ByteString.copyFrom(bytes); + ByteString prefix = ByteString.copyFrom(bytes, 0, 500); + ByteString suffix = ByteString.copyFrom(bytes, 400, 600); + assertTrue(string.endsWith(ByteString.EMPTY)); + assertTrue(string.endsWith(string)); + assertTrue(string.endsWith(suffix)); + assertFalse(string.endsWith(prefix)); + assertFalse(suffix.endsWith(prefix)); + assertFalse(prefix.endsWith(suffix)); + assertFalse(ByteString.EMPTY.endsWith(suffix)); + assertTrue(ByteString.EMPTY.endsWith(ByteString.EMPTY)); + } + + static List makeConcretePieces(byte[] referenceBytes) { + List pieces = new ArrayList(); + // Starting length should be small enough that we'll do some concatenating by + // copying if we just concatenate all these pieces together. + for (int start = 0, length = 16; start < referenceBytes.length; start += length) { + length = (length << 1) - 1; + if (start + length > referenceBytes.length) { + length = referenceBytes.length - start; + } + pieces.add(ByteString.copyFrom(referenceBytes, start, length)); + } + return pieces; + } + + private byte[] substringUsingWriteTo( + ByteString data, int offset, int length) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + data.writeTo(output, offset, length); + return output.toByteArray(); + } + + public void testWriteToOutputStream() throws Exception { + // Choose a size large enough so when two ByteStrings are concatenated they + // won't be merged into one byte array due to some optimizations. + final int dataSize = ByteString.CONCATENATE_BY_COPY_SIZE + 1; + byte[] data1 = new byte[dataSize]; + for (int i = 0; i < data1.length; i++) { + data1[i] = (byte) 1; + } + data1[1] = (byte) 11; + // Test LiteralByteString.writeTo(OutputStream,int,int) + LiteralByteString left = new LiteralByteString(data1); + byte[] result = substringUsingWriteTo(left, 1, 1); + assertEquals(1, result.length); + assertEquals((byte) 11, result[0]); + + byte[] data2 = new byte[dataSize]; + for (int i = 0; i < data1.length; i++) { + data2[i] = (byte) 2; + } + LiteralByteString right = new LiteralByteString(data2); + // Concatenate two ByteStrings to create a RopeByteString. + ByteString root = left.concat(right); + // Make sure we are actually testing a RopeByteString with a simple tree + // structure. + assertEquals(1, root.getTreeDepth()); + // Write parts of the left node. + result = substringUsingWriteTo(root, 0, dataSize); + assertEquals(dataSize, result.length); + assertEquals((byte) 1, result[0]); + assertEquals((byte) 1, result[dataSize - 1]); + // Write parts of the right node. + result = substringUsingWriteTo(root, dataSize, dataSize); + assertEquals(dataSize, result.length); + assertEquals((byte) 2, result[0]); + assertEquals((byte) 2, result[dataSize - 1]); + // Write a segment of bytes that runs across both nodes. + result = substringUsingWriteTo(root, dataSize / 2, dataSize); + assertEquals(dataSize, result.length); + assertEquals((byte) 1, result[0]); + assertEquals((byte) 1, result[dataSize - dataSize / 2 - 1]); + assertEquals((byte) 2, result[dataSize - dataSize / 2]); + assertEquals((byte) 2, result[dataSize - 1]); + } +} diff --git a/java/src/test/java/com/google/protobuf/CheckUtf8Test.java b/java/src/test/java/com/google/protobuf/CheckUtf8Test.java new file mode 100644 index 0000000..97bf1c7 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/CheckUtf8Test.java @@ -0,0 +1,141 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import proto2_test_check_utf8.TestCheckUtf8.BytesWrapper; +import proto2_test_check_utf8.TestCheckUtf8.StringWrapper; +import proto2_test_check_utf8_size.TestCheckUtf8Size.BytesWrapperSize; +import proto2_test_check_utf8_size.TestCheckUtf8Size.StringWrapperSize; +import junit.framework.TestCase; + +/** + * Test that protos generated with file option java_string_check_utf8 do in + * fact perform appropriate UTF-8 checks. + * + * @author jbaum@google.com (Jacob Butcher) + */ +public class CheckUtf8Test extends TestCase { + + private static final String UTF8_BYTE_STRING_TEXT = "some text"; + private static final ByteString UTF8_BYTE_STRING = + ByteString.copyFromUtf8(UTF8_BYTE_STRING_TEXT); + private static final ByteString NON_UTF8_BYTE_STRING = + ByteString.copyFrom(new byte[]{(byte) 0x80}); // A lone continuation byte. + + public void testBuildRequiredStringWithGoodUtf8() throws Exception { + assertEquals(UTF8_BYTE_STRING_TEXT, + StringWrapper.newBuilder().setReqBytes(UTF8_BYTE_STRING).getReq()); + } + + public void testParseRequiredStringWithGoodUtf8() throws Exception { + ByteString serialized = + BytesWrapper.newBuilder().setReq(UTF8_BYTE_STRING).build().toByteString(); + assertEquals(UTF8_BYTE_STRING_TEXT, + StringWrapper.PARSER.parseFrom(serialized).getReq()); + } + + public void testBuildRequiredStringWithBadUtf8() throws Exception { + try { + StringWrapper.newBuilder().setReqBytes(NON_UTF8_BYTE_STRING); + fail("Expected IllegalArgumentException for non UTF-8 byte string."); + } catch (IllegalArgumentException exception) { + assertEquals("Byte string is not UTF-8.", exception.getMessage()); + } + } + + public void testBuildOptionalStringWithBadUtf8() throws Exception { + try { + StringWrapper.newBuilder().setOptBytes(NON_UTF8_BYTE_STRING); + fail("Expected IllegalArgumentException for non UTF-8 byte string."); + } catch (IllegalArgumentException exception) { + assertEquals("Byte string is not UTF-8.", exception.getMessage()); + } + } + + public void testBuildRepeatedStringWithBadUtf8() throws Exception { + try { + StringWrapper.newBuilder().addRepBytes(NON_UTF8_BYTE_STRING); + fail("Expected IllegalArgumentException for non UTF-8 byte string."); + } catch (IllegalArgumentException exception) { + assertEquals("Byte string is not UTF-8.", exception.getMessage()); + } + } + + public void testParseRequiredStringWithBadUtf8() throws Exception { + ByteString serialized = + BytesWrapper.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString(); + try { + StringWrapper.PARSER.parseFrom(serialized); + fail("Expected InvalidProtocolBufferException for non UTF-8 byte string."); + } catch (InvalidProtocolBufferException exception) { + assertEquals("Protocol message had invalid UTF-8.", exception.getMessage()); + } + } + + public void testBuildRequiredStringWithBadUtf8Size() throws Exception { + try { + StringWrapperSize.newBuilder().setReqBytes(NON_UTF8_BYTE_STRING); + fail("Expected IllegalArgumentException for non UTF-8 byte string."); + } catch (IllegalArgumentException exception) { + assertEquals("Byte string is not UTF-8.", exception.getMessage()); + } + } + + public void testBuildOptionalStringWithBadUtf8Size() throws Exception { + try { + StringWrapperSize.newBuilder().setOptBytes(NON_UTF8_BYTE_STRING); + fail("Expected IllegalArgumentException for non UTF-8 byte string."); + } catch (IllegalArgumentException exception) { + assertEquals("Byte string is not UTF-8.", exception.getMessage()); + } + } + + public void testBuildRepeatedStringWithBadUtf8Size() throws Exception { + try { + StringWrapperSize.newBuilder().addRepBytes(NON_UTF8_BYTE_STRING); + fail("Expected IllegalArgumentException for non UTF-8 byte string."); + } catch (IllegalArgumentException exception) { + assertEquals("Byte string is not UTF-8.", exception.getMessage()); + } + } + + public void testParseRequiredStringWithBadUtf8Size() throws Exception { + ByteString serialized = + BytesWrapperSize.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString(); + try { + StringWrapperSize.PARSER.parseFrom(serialized); + fail("Expected InvalidProtocolBufferException for non UTF-8 byte string."); + } catch (InvalidProtocolBufferException exception) { + assertEquals("Protocol message had invalid UTF-8.", exception.getMessage()); + } + } + +} diff --git a/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java index 33d60d1..3b50e49 100644 --- a/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java +++ b/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java @@ -30,15 +30,20 @@ package com.google.protobuf; +import protobuf_unittest.UnittestProto.BoolMessage; +import protobuf_unittest.UnittestProto.Int32Message; +import protobuf_unittest.UnittestProto.Int64Message; import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestRecursiveMessage; import junit.framework.TestCase; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.FilterInputStream; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; /** * Unit test for {@link CodedInputStream}. @@ -85,28 +90,54 @@ public class CodedInputStreamTest extends TestCase { } } + private void assertDataConsumed(byte[] data, CodedInputStream input) + throws IOException { + assertEquals(data.length, input.getTotalBytesRead()); + assertTrue(input.isAtEnd()); + } + /** * Parses the given bytes using readRawVarint32() and readRawVarint64() and * checks that the result matches the given value. */ private void assertReadVarint(byte[] data, long value) throws Exception { CodedInputStream input = CodedInputStream.newInstance(data); - assertEquals((int)value, input.readRawVarint32()); + assertEquals((int) value, input.readRawVarint32()); + assertDataConsumed(data, input); input = CodedInputStream.newInstance(data); assertEquals(value, input.readRawVarint64()); - assertTrue(input.isAtEnd()); + assertDataConsumed(data, input); + + input = CodedInputStream.newInstance(data); + assertEquals(value, input.readRawVarint64SlowPath()); + assertDataConsumed(data, input); + + input = CodedInputStream.newInstance(data); + assertTrue(input.skipField(WireFormat.WIRETYPE_VARINT)); + assertDataConsumed(data, input); // Try different block sizes. for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { input = CodedInputStream.newInstance( new SmallBlockInputStream(data, blockSize)); - assertEquals((int)value, input.readRawVarint32()); + assertEquals((int) value, input.readRawVarint32()); + assertDataConsumed(data, input); input = CodedInputStream.newInstance( new SmallBlockInputStream(data, blockSize)); assertEquals(value, input.readRawVarint64()); - assertTrue(input.isAtEnd()); + assertDataConsumed(data, input); + + input = CodedInputStream.newInstance( + new SmallBlockInputStream(data, blockSize)); + assertEquals(value, input.readRawVarint64SlowPath()); + assertDataConsumed(data, input); + + input = CodedInputStream.newInstance( + new SmallBlockInputStream(data, blockSize)); + assertTrue(input.skipField(WireFormat.WIRETYPE_VARINT)); + assertDataConsumed(data, input); } // Try reading direct from an InputStream. We want to verify that it @@ -115,7 +146,7 @@ public class CodedInputStreamTest extends TestCase { byte[] longerData = new byte[data.length + 1]; System.arraycopy(data, 0, longerData, 0, data.length); InputStream rawInput = new ByteArrayInputStream(longerData); - assertEquals((int)value, CodedInputStream.readRawVarint32(rawInput)); + assertEquals((int) value, CodedInputStream.readRawVarint32(rawInput)); assertEquals(1, rawInput.available()); } @@ -143,6 +174,14 @@ public class CodedInputStreamTest extends TestCase { assertEquals(expected.getMessage(), e.getMessage()); } + input = CodedInputStream.newInstance(data); + try { + input.readRawVarint64SlowPath(); + fail("Should have thrown an exception."); + } catch (InvalidProtocolBufferException e) { + assertEquals(expected.getMessage(), e.getMessage()); + } + // Make sure we get the same error when reading direct from an InputStream. try { CodedInputStream.readRawVarint32(new ByteArrayInputStream(data)); @@ -311,6 +350,7 @@ public class CodedInputStreamTest extends TestCase { } } + /** * Test that a bug in skipRawBytes() has been fixed: if the skip skips * exactly up to a limit, this should not break things. @@ -331,14 +371,11 @@ public class CodedInputStreamTest extends TestCase { * that buffer, this should not break things. */ public void testSkipRawBytesPastEndOfBufferWithLimit() throws Exception { - System.out.printf("testSkipRawBytesPastEndOfBufferWithLimit: E ...\n"); - byte[] rawBytes = new byte[] { 1, 2, 3, 4, 5 }; CodedInputStream input = CodedInputStream.newInstance( new SmallBlockInputStream(rawBytes, 3)); int limit = input.pushLimit(4); - System.out.printf("testSkipRawBytesPastEndOfBufferWithLimit: limit=%d\n", limit); // In order to expose the bug we need to read at least one byte to prime the // buffer inside the CodedInputStream. assertEquals(1, input.readRawByte()); @@ -347,15 +384,13 @@ public class CodedInputStreamTest extends TestCase { assertTrue(input.isAtEnd()); input.popLimit(limit); assertEquals(5, input.readRawByte()); - - System.out.printf("testSkipRawBytesPastEndOfBufferWithLimit: X ...\n"); } public void testReadHugeBlob() throws Exception { // Allocate and initialize a 1MB blob. byte[] blob = new byte[1 << 20]; for (int i = 0; i < blob.length; i++) { - blob[i] = (byte)i; + blob[i] = (byte) i; } // Make a message containing it. @@ -442,16 +477,23 @@ public class CodedInputStreamTest extends TestCase { } } + private void checkSizeLimitExceeded(InvalidProtocolBufferException e) { + assertEquals( + InvalidProtocolBufferException.sizeLimitExceeded().getMessage(), + e.getMessage()); + } + public void testSizeLimit() throws Exception { CodedInputStream input = CodedInputStream.newInstance( - TestUtil.getAllSet().toByteString().newInput()); + new SmallBlockInputStream( + TestUtil.getAllSet().toByteString().newInput(), 16)); input.setSizeLimit(16); try { TestAllTypes.parseFrom(input); fail("Should have thrown an exception!"); - } catch (InvalidProtocolBufferException e) { - // success. + } catch (InvalidProtocolBufferException expected) { + checkSizeLimitExceeded(expected); } } @@ -465,8 +507,8 @@ public class CodedInputStreamTest extends TestCase { try { input.readRawByte(); fail("Should have thrown an exception!"); - } catch (InvalidProtocolBufferException e) { - // success. + } catch (InvalidProtocolBufferException expected) { + checkSizeLimitExceeded(expected); } input.resetSizeCounter(); @@ -474,28 +516,50 @@ public class CodedInputStreamTest extends TestCase { input.readRawByte(); // No exception thrown. input.resetSizeCounter(); assertEquals(0, input.getTotalBytesRead()); + input.readRawBytes(16); + assertEquals(16, input.getTotalBytesRead()); + input.resetSizeCounter(); try { - input.readRawBytes(16); // Hits limit again. + input.readRawBytes(17); // Hits limit again. fail("Should have thrown an exception!"); - } catch (InvalidProtocolBufferException e) { - // success. + } catch (InvalidProtocolBufferException expected) { + checkSizeLimitExceeded(expected); + } + } + + public void testSizeLimitMultipleMessages() throws Exception { + byte[] bytes = new byte[256]; + for (int i = 0; i < bytes.length; i++) { + bytes[i] = (byte) i; + } + CodedInputStream input = CodedInputStream.newInstance( + new SmallBlockInputStream(bytes, 7)); + input.setSizeLimit(16); + for (int i = 0; i < 256 / 16; i++) { + byte[] message = input.readRawBytes(16); + for (int j = 0; j < message.length; j++) { + assertEquals(i * 16 + j, message[j] & 0xff); + } + assertEquals(16, input.getTotalBytesRead()); + input.resetSizeCounter(); + assertEquals(0, input.getTotalBytesRead()); } } /** - * Tests that if we read an string that contains invalid UTF-8, no exception + * Tests that if we readString invalid UTF-8 bytes, no exception * is thrown. Instead, the invalid bytes are replaced with the Unicode * "replacement character" U+FFFD. */ - public void testReadInvalidUtf8() throws Exception { + public void testReadStringInvalidUtf8() throws Exception { ByteString.Output rawOutput = ByteString.newOutput(); CodedOutputStream output = CodedOutputStream.newInstance(rawOutput); int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED); output.writeRawVarint32(tag); output.writeRawVarint32(1); - output.writeRawBytes(new byte[] { (byte)0x80 }); + output.writeRawBytes(new byte[] { (byte) 0x80 }); output.flush(); CodedInputStream input = rawOutput.toByteString().newCodedInput(); @@ -504,13 +568,37 @@ public class CodedInputStreamTest extends TestCase { assertEquals(0xfffd, text.charAt(0)); } + /** + * Tests that if we readStringRequireUtf8 invalid UTF-8 bytes, an + * InvalidProtocolBufferException is thrown. + */ + public void testReadStringRequireUtf8InvalidUtf8() throws Exception { + ByteString.Output rawOutput = ByteString.newOutput(); + CodedOutputStream output = CodedOutputStream.newInstance(rawOutput); + + int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED); + output.writeRawVarint32(tag); + output.writeRawVarint32(1); + output.writeRawBytes(new byte[] { (byte) 0x80 }); + output.flush(); + + CodedInputStream input = rawOutput.toByteString().newCodedInput(); + assertEquals(tag, input.readTag()); + try { + input.readStringRequireUtf8(); + fail("Expected invalid UTF-8 exception."); + } catch (InvalidProtocolBufferException exception) { + assertEquals("Protocol message had invalid UTF-8.", exception.getMessage()); + } + } + public void testReadFromSlice() throws Exception { byte[] bytes = bytes(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); CodedInputStream in = CodedInputStream.newInstance(bytes, 3, 5); assertEquals(0, in.getTotalBytesRead()); for (int i = 3; i < 8; i++) { assertEquals(i, in.readRawByte()); - assertEquals(i-2, in.getTotalBytesRead()); + assertEquals(i - 2, in.getTotalBytesRead()); } // eof assertEquals(0, in.readTag()); @@ -530,4 +618,152 @@ public class CodedInputStreamTest extends TestCase { } } } + + public void testReadByteArray() throws Exception { + ByteString.Output rawOutput = ByteString.newOutput(); + CodedOutputStream output = CodedOutputStream.newInstance(rawOutput); + // Zero-sized bytes field. + output.writeRawVarint32(0); + // One one-byte bytes field + output.writeRawVarint32(1); + output.writeRawBytes(new byte[] { (byte) 23 }); + // Another one-byte bytes field + output.writeRawVarint32(1); + output.writeRawBytes(new byte[] { (byte) 45 }); + // A bytes field large enough that won't fit into the 4K buffer. + final int bytesLength = 16 * 1024; + byte[] bytes = new byte[bytesLength]; + bytes[0] = (byte) 67; + bytes[bytesLength - 1] = (byte) 89; + output.writeRawVarint32(bytesLength); + output.writeRawBytes(bytes); + + output.flush(); + CodedInputStream inputStream = rawOutput.toByteString().newCodedInput(); + + byte[] result = inputStream.readByteArray(); + assertEquals(0, result.length); + result = inputStream.readByteArray(); + assertEquals(1, result.length); + assertEquals((byte) 23, result[0]); + result = inputStream.readByteArray(); + assertEquals(1, result.length); + assertEquals((byte) 45, result[0]); + result = inputStream.readByteArray(); + assertEquals(bytesLength, result.length); + assertEquals((byte) 67, result[0]); + assertEquals((byte) 89, result[bytesLength - 1]); + } + + public void testReadByteBuffer() throws Exception { + ByteString.Output rawOutput = ByteString.newOutput(); + CodedOutputStream output = CodedOutputStream.newInstance(rawOutput); + // Zero-sized bytes field. + output.writeRawVarint32(0); + // One one-byte bytes field + output.writeRawVarint32(1); + output.writeRawBytes(new byte[]{(byte) 23}); + // Another one-byte bytes field + output.writeRawVarint32(1); + output.writeRawBytes(new byte[]{(byte) 45}); + // A bytes field large enough that won't fit into the 4K buffer. + final int bytesLength = 16 * 1024; + byte[] bytes = new byte[bytesLength]; + bytes[0] = (byte) 67; + bytes[bytesLength - 1] = (byte) 89; + output.writeRawVarint32(bytesLength); + output.writeRawBytes(bytes); + + output.flush(); + CodedInputStream inputStream = rawOutput.toByteString().newCodedInput(); + + ByteBuffer result = inputStream.readByteBuffer(); + assertEquals(0, result.capacity()); + result = inputStream.readByteBuffer(); + assertEquals(1, result.capacity()); + assertEquals((byte) 23, result.get()); + result = inputStream.readByteBuffer(); + assertEquals(1, result.capacity()); + assertEquals((byte) 45, result.get()); + result = inputStream.readByteBuffer(); + assertEquals(bytesLength, result.capacity()); + assertEquals((byte) 67, result.get()); + result.position(bytesLength - 1); + assertEquals((byte) 89, result.get()); + } + + public void testReadByteBufferAliasing() throws Exception { + ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream(); + CodedOutputStream output = CodedOutputStream.newInstance(byteArrayStream); + // Zero-sized bytes field. + output.writeRawVarint32(0); + // One one-byte bytes field + output.writeRawVarint32(1); + output.writeRawBytes(new byte[]{(byte) 23}); + // Another one-byte bytes field + output.writeRawVarint32(1); + output.writeRawBytes(new byte[]{(byte) 45}); + // A bytes field large enough that won't fit into the 4K buffer. + final int bytesLength = 16 * 1024; + byte[] bytes = new byte[bytesLength]; + bytes[0] = (byte) 67; + bytes[bytesLength - 1] = (byte) 89; + output.writeRawVarint32(bytesLength); + output.writeRawBytes(bytes); + output.flush(); + byte[] data = byteArrayStream.toByteArray(); + + // Without aliasing + CodedInputStream inputStream = CodedInputStream.newInstance(data); + ByteBuffer result = inputStream.readByteBuffer(); + assertEquals(0, result.capacity()); + result = inputStream.readByteBuffer(); + assertTrue(result.array() != data); + assertEquals(1, result.capacity()); + assertEquals((byte) 23, result.get()); + result = inputStream.readByteBuffer(); + assertTrue(result.array() != data); + assertEquals(1, result.capacity()); + assertEquals((byte) 45, result.get()); + result = inputStream.readByteBuffer(); + assertTrue(result.array() != data); + assertEquals(bytesLength, result.capacity()); + assertEquals((byte) 67, result.get()); + result.position(bytesLength - 1); + assertEquals((byte) 89, result.get()); + + // Enable aliasing + inputStream = CodedInputStream.newInstance(data); + inputStream.enableAliasing(true); + result = inputStream.readByteBuffer(); + assertEquals(0, result.capacity()); + result = inputStream.readByteBuffer(); + assertTrue(result.array() == data); + assertEquals(1, result.capacity()); + assertEquals((byte) 23, result.get()); + result = inputStream.readByteBuffer(); + assertTrue(result.array() == data); + assertEquals(1, result.capacity()); + assertEquals((byte) 45, result.get()); + result = inputStream.readByteBuffer(); + assertTrue(result.array() == data); + assertEquals(bytesLength, result.capacity()); + assertEquals((byte) 67, result.get()); + result.position(bytesLength - 1); + assertEquals((byte) 89, result.get()); + } + + public void testCompatibleTypes() throws Exception { + long data = 0x100000000L; + Int64Message message = Int64Message.newBuilder().setData(data).build(); + ByteString serialized = message.toByteString(); + + // Test int64(long) is compatible with bool(boolean) + BoolMessage msg2 = BoolMessage.parseFrom(serialized); + assertTrue(msg2.getData()); + + // Test int64(long) is compatible with int32(int) + Int32Message msg3 = Int32Message.parseFrom(serialized); + assertEquals((int) data, msg3.getData()); + } } diff --git a/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java b/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java index c42b485..da70be4 100644 --- a/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java +++ b/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java @@ -30,14 +30,16 @@ package com.google.protobuf; +import protobuf_unittest.UnittestProto.SparseEnumMessage; import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestPackedTypes; +import protobuf_unittest.UnittestProto.TestSparseEnum; import junit.framework.TestCase; import java.io.ByteArrayOutputStream; +import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -301,4 +303,99 @@ public class CodedOutputStreamTest extends TestCase { assertEqualBytes(TestUtil.getGoldenPackedFieldsMessage().toByteArray(), rawBytes); } + + /** Test writing a message containing a negative enum value. This used to + * fail because the size was not properly computed as a sign-extended varint. + */ + public void testWriteMessageWithNegativeEnumValue() throws Exception { + SparseEnumMessage message = SparseEnumMessage.newBuilder() + .setSparseEnum(TestSparseEnum.SPARSE_E) .build(); + assertTrue(message.getSparseEnum().getNumber() < 0); + byte[] rawBytes = message.toByteArray(); + SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes); + assertEquals(TestSparseEnum.SPARSE_E, message2.getSparseEnum()); + } + + /** Test getTotalBytesWritten() */ + public void testGetTotalBytesWritten() throws Exception { + final int BUFFER_SIZE = 4 * 1024; + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(BUFFER_SIZE); + CodedOutputStream codedStream = CodedOutputStream.newInstance(outputStream); + byte[] value = "abcde".getBytes("UTF-8"); + for (int i = 0; i < 1024; ++i) { + codedStream.writeRawBytes(value, 0, value.length); + } + // Make sure we have written more bytes than the buffer could hold. This is + // to make the test complete. + assertTrue(codedStream.getTotalBytesWritten() > BUFFER_SIZE); + assertEquals(value.length * 1024, codedStream.getTotalBytesWritten()); + } + + public void testWriteToByteBuffer() throws Exception { + final int bufferSize = 16 * 1024; + ByteBuffer buffer = ByteBuffer.allocate(bufferSize); + CodedOutputStream codedStream = CodedOutputStream.newInstance(buffer); + // Write raw bytes into the ByteBuffer. + final int length1 = 5000; + for (int i = 0; i < length1; i++) { + codedStream.writeRawByte((byte) 1); + } + final int length2 = 8 * 1024; + byte[] data = new byte[length2]; + for (int i = 0; i < length2; i++) { + data[i] = (byte) 2; + } + codedStream.writeRawBytes(data); + final int length3 = bufferSize - length1 - length2; + for (int i = 0; i < length3; i++) { + codedStream.writeRawByte((byte) 3); + } + codedStream.flush(); + + // Check that data is correctly written to the ByteBuffer. + assertEquals(0, buffer.remaining()); + buffer.flip(); + for (int i = 0; i < length1; i++) { + assertEquals((byte) 1, buffer.get()); + } + for (int i = 0; i < length2; i++) { + assertEquals((byte) 2, buffer.get()); + } + for (int i = 0; i < length3; i++) { + assertEquals((byte) 3, buffer.get()); + } + } + + public void testWriteByteBuffer() throws Exception { + byte[] value = "abcde".getBytes("UTF-8"); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + CodedOutputStream codedStream = CodedOutputStream.newInstance(outputStream); + ByteBuffer byteBuffer = ByteBuffer.wrap(value, 0, 1); + // This will actually write 5 bytes into the CodedOutputStream as the + // ByteBuffer's capacity() is 5. + codedStream.writeRawBytes(byteBuffer); + // The above call shouldn't affect the ByteBuffer's state. + assertEquals(0, byteBuffer.position()); + assertEquals(1, byteBuffer.limit()); + + // The correct way to write part of an array using ByteBuffer. + codedStream.writeRawBytes(ByteBuffer.wrap(value, 2, 1).slice()); + + codedStream.flush(); + byte[] result = outputStream.toByteArray(); + assertEquals(6, result.length); + for (int i = 0; i < 5; i++) { + assertEquals(value[i], result[i]); + } + assertEquals(value[2], result[5]); + } + + public void testWriteByteArrayWithOffsets() throws Exception { + byte[] fullArray = bytes(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88); + byte[] destination = new byte[4]; + CodedOutputStream codedStream = CodedOutputStream.newInstance(destination); + codedStream.writeByteArrayNoTag(fullArray, 2, 2); + assertEqualBytes(bytes(0x02, 0x33, 0x44, 0x00), destination); + assertEquals(3, codedStream.getTotalBytesWritten()); + } } diff --git a/java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java b/java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java new file mode 100644 index 0000000..1f8bb44 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java @@ -0,0 +1,80 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import protobuf_unittest.UnittestProto.TestDeprecatedFields; + +import junit.framework.TestCase; + +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Method; +/** + * Test field deprecation + * + * @author birdo@google.com (Roberto Scaramuzzi) + */ +public class DeprecatedFieldTest extends TestCase { + private String[] deprecatedGetterNames = { + "hasDeprecatedInt32", + "getDeprecatedInt32"}; + + private String[] deprecatedBuilderGetterNames = { + "hasDeprecatedInt32", + "getDeprecatedInt32", + "clearDeprecatedInt32"}; + + private String[] deprecatedBuilderSetterNames = { + "setDeprecatedInt32"}; + + public void testDeprecatedField() throws Exception { + Class deprecatedFields = TestDeprecatedFields.class; + Class deprecatedFieldsBuilder = TestDeprecatedFields.Builder.class; + for (String name : deprecatedGetterNames) { + Method method = deprecatedFields.getMethod(name); + assertTrue("Method " + name + " should be deprecated", + isDeprecated(method)); + } + for (String name : deprecatedBuilderGetterNames) { + Method method = deprecatedFieldsBuilder.getMethod(name); + assertTrue("Method " + name + " should be deprecated", + isDeprecated(method)); + } + for (String name : deprecatedBuilderSetterNames) { + Method method = deprecatedFieldsBuilder.getMethod(name, int.class); + assertTrue("Method " + name + " should be deprecated", + isDeprecated(method)); + } + } + + private boolean isDeprecated(AnnotatedElement annotated) { + return annotated.isAnnotationPresent(Deprecated.class); + } +} diff --git a/java/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/src/test/java/com/google/protobuf/DescriptorsTest.java index f41d070..30e0149 100644 --- a/java/src/test/java/com/google/protobuf/DescriptorsTest.java +++ b/java/src/test/java/com/google/protobuf/DescriptorsTest.java @@ -31,12 +31,15 @@ package com.google.protobuf; import com.google.protobuf.DescriptorProtos.DescriptorProto; +import com.google.protobuf.DescriptorProtos.EnumDescriptorProto; +import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto; import com.google.protobuf.DescriptorProtos.FieldDescriptorProto; import com.google.protobuf.DescriptorProtos.FileDescriptorProto; import com.google.protobuf.Descriptors.DescriptorValidationException; import com.google.protobuf.Descriptors.FileDescriptor; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.OneofDescriptor; import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.ServiceDescriptor; @@ -51,15 +54,19 @@ import protobuf_unittest.UnittestProto.ForeignMessage; import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestAllExtensions; import protobuf_unittest.UnittestProto.TestExtremeDefaultValues; +import protobuf_unittest.UnittestProto.TestMultipleExtensionRanges; import protobuf_unittest.UnittestProto.TestRequired; import protobuf_unittest.UnittestProto.TestService; import protobuf_unittest.UnittestCustomOptions; +import protobuf_unittest.TestCustomOptions; + import junit.framework.TestCase; import java.util.Arrays; import java.util.Collections; +import java.util.List; /** * Unit test for {@link Descriptors}. @@ -71,6 +78,7 @@ public class DescriptorsTest extends TestCase { // Regression test for bug where referencing a FieldDescriptor.Type value // before a FieldDescriptorProto.Type value would yield a // ExceptionInInitializerError. + @SuppressWarnings("unused") private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL; public void testFieldTypeEnumMapping() throws Exception { @@ -304,6 +312,7 @@ public class DescriptorsTest extends TestCase { EnumValueDescriptor value = ForeignEnum.FOREIGN_FOO.getValueDescriptor(); assertEquals(value, enumType.getValues().get(0)); assertEquals("FOREIGN_FOO", value.getName()); + assertEquals("FOREIGN_FOO", value.toString()); assertEquals(4, value.getNumber()); assertEquals(value, enumType.findValueByName("FOREIGN_FOO")); assertEquals(value, enumType.findValueByNumber(4)); @@ -320,7 +329,6 @@ public class DescriptorsTest extends TestCase { assertEquals("protobuf_unittest.TestService", service.getFullName()); assertEquals(UnittestProto.getDescriptor(), service.getFile()); - assertEquals(2, service.getMethods().size()); MethodDescriptor fooMethod = service.getMethods().get(0); assertEquals("Foo", fooMethod.getName()); @@ -347,8 +355,12 @@ public class DescriptorsTest extends TestCase { public void testCustomOptions() throws Exception { + // Get the descriptor indirectly from a dependent proto class. This is to + // ensure that when a proto class is loaded, custom options defined in its + // dependencies are also properly initialized. Descriptor descriptor = - UnittestCustomOptions.TestMessageWithCustomOptions.getDescriptor(); + TestCustomOptions.TestMessageWithCustomOptionsContainer.getDescriptor() + .findFieldByName("field").getMessageType(); assertTrue( descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1)); @@ -425,7 +437,7 @@ public class DescriptorsTest extends TestCase { UnittestEnormousDescriptor.getDescriptor() .toProto().getSerializedSize() > 65536); } - + /** * Tests that the DescriptorValidationException works as intended. */ @@ -444,7 +456,7 @@ public class DescriptorsTest extends TestCase { .build()) .build(); try { - Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, + Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]); fail("DescriptorValidationException expected"); } catch (DescriptorValidationException e) { @@ -456,4 +468,241 @@ public class DescriptorsTest extends TestCase { assertTrue(e.getCause().getMessage().indexOf("invalid") != -1); } } + + /** + * Tests the translate/crosslink for an example where a message field's name + * and type name are the same. + */ + public void testDescriptorComplexCrosslink() throws Exception { + FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder() + .setName("foo.proto") + .addMessageType(DescriptorProto.newBuilder() + .setName("Foo") + .addField(FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setType(FieldDescriptorProto.Type.TYPE_INT32) + .setName("foo") + .setNumber(1) + .build()) + .build()) + .addMessageType(DescriptorProto.newBuilder() + .setName("Bar") + .addField(FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setTypeName("Foo") + .setName("Foo") + .setNumber(1) + .build()) + .build()) + .build(); + // translate and crosslink + FileDescriptor file = + Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, + new FileDescriptor[0]); + // verify resulting descriptors + assertNotNull(file); + List msglist = file.getMessageTypes(); + assertNotNull(msglist); + assertTrue(msglist.size() == 2); + boolean barFound = false; + for (Descriptor desc : msglist) { + if (desc.getName().equals("Bar")) { + barFound = true; + assertNotNull(desc.getFields()); + List fieldlist = desc.getFields(); + assertNotNull(fieldlist); + assertTrue(fieldlist.size() == 1); + assertTrue(fieldlist.get(0).getType() == FieldDescriptor.Type.MESSAGE); + assertTrue(fieldlist.get(0).getMessageType().getName().equals("Foo")); + } + } + assertTrue(barFound); + } + + public void testDependencyOrder() throws Exception { + FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() + .setName("foo.proto").build(); + FileDescriptorProto barProto = FileDescriptorProto.newBuilder() + .setName("bar.proto") + .addDependency("foo.proto") + .build(); + FileDescriptorProto bazProto = FileDescriptorProto.newBuilder() + .setName("baz.proto") + .addDependency("foo.proto") + .addDependency("bar.proto") + .addPublicDependency(0) + .addPublicDependency(1) + .build(); + FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, + new FileDescriptor[0]); + FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto, + new FileDescriptor[] {fooFile}); + + // Items in the FileDescriptor array can be in any order. + Descriptors.FileDescriptor.buildFrom(bazProto, + new FileDescriptor[] {fooFile, barFile}); + Descriptors.FileDescriptor.buildFrom(bazProto, + new FileDescriptor[] {barFile, fooFile}); + } + + public void testInvalidPublicDependency() throws Exception { + FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() + .setName("foo.proto").build(); + FileDescriptorProto barProto = FileDescriptorProto.newBuilder() + .setName("boo.proto") + .addDependency("foo.proto") + .addPublicDependency(1) // Error, should be 0. + .build(); + FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, + new FileDescriptor[0]); + try { + Descriptors.FileDescriptor.buildFrom(barProto, + new FileDescriptor[] {fooFile}); + fail("DescriptorValidationException expected"); + } catch (DescriptorValidationException e) { + assertTrue( + e.getMessage().indexOf("Invalid public dependency index.") != -1); + } + } + + public void testHiddenDependency() throws Exception { + FileDescriptorProto barProto = FileDescriptorProto.newBuilder() + .setName("bar.proto") + .addMessageType(DescriptorProto.newBuilder().setName("Bar")) + .build(); + FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder() + .setName("forward.proto") + .addDependency("bar.proto") + .build(); + FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() + .setName("foo.proto") + .addDependency("forward.proto") + .addMessageType(DescriptorProto.newBuilder() + .setName("Foo") + .addField(FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setTypeName("Bar") + .setName("bar") + .setNumber(1))) + .build(); + FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom( + barProto, new FileDescriptor[0]); + FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom( + forwardProto, new FileDescriptor[] {barFile}); + + try { + Descriptors.FileDescriptor.buildFrom( + fooProto, new FileDescriptor[] {forwardFile}); + fail("DescriptorValidationException expected"); + } catch (DescriptorValidationException e) { + assertTrue(e.getMessage().indexOf("Bar") != -1); + assertTrue(e.getMessage().indexOf("is not defined") != -1); + } + } + + public void testPublicDependency() throws Exception { + FileDescriptorProto barProto = FileDescriptorProto.newBuilder() + .setName("bar.proto") + .addMessageType(DescriptorProto.newBuilder().setName("Bar")) + .build(); + FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder() + .setName("forward.proto") + .addDependency("bar.proto") + .addPublicDependency(0) + .build(); + FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() + .setName("foo.proto") + .addDependency("forward.proto") + .addMessageType(DescriptorProto.newBuilder() + .setName("Foo") + .addField(FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setTypeName("Bar") + .setName("bar") + .setNumber(1))) + .build(); + FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom( + barProto, new FileDescriptor[0]); + FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom( + forwardProto, new FileDescriptor[]{barFile}); + Descriptors.FileDescriptor.buildFrom( + fooProto, new FileDescriptor[] {forwardFile}); + } + + /** + * Tests the translate/crosslink for an example with a more complex namespace + * referencing. + */ + public void testComplexNamespacePublicDependency() throws Exception { + FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() + .setName("bar.proto") + .setPackage("a.b.c.d.bar.shared") + .addEnumType(EnumDescriptorProto.newBuilder() + .setName("MyEnum") + .addValue(EnumValueDescriptorProto.newBuilder() + .setName("BLAH") + .setNumber(1))) + .build(); + FileDescriptorProto barProto = FileDescriptorProto.newBuilder() + .setName("foo.proto") + .addDependency("bar.proto") + .setPackage("a.b.c.d.foo.shared") + .addMessageType(DescriptorProto.newBuilder() + .setName("MyMessage") + .addField(FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) + .setTypeName("bar.shared.MyEnum") + .setName("MyField") + .setNumber(1))) + .build(); + // translate and crosslink + FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom( + fooProto, new FileDescriptor[0]); + FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom( + barProto, new FileDescriptor[]{fooFile}); + // verify resulting descriptors + assertNotNull(barFile); + List msglist = barFile.getMessageTypes(); + assertNotNull(msglist); + assertTrue(msglist.size() == 1); + Descriptor desc = msglist.get(0); + if (desc.getName().equals("MyMessage")) { + assertNotNull(desc.getFields()); + List fieldlist = desc.getFields(); + assertNotNull(fieldlist); + assertTrue(fieldlist.size() == 1); + FieldDescriptor field = fieldlist.get(0); + assertTrue(field.getType() == FieldDescriptor.Type.ENUM); + assertTrue(field.getEnumType().getName().equals("MyEnum")); + assertTrue(field.getEnumType().getFile().getName().equals("bar.proto")); + assertTrue(field.getEnumType().getFile().getPackage().equals( + "a.b.c.d.bar.shared")); + } + } + + public void testOneofDescriptor() throws Exception { + Descriptor messageType = TestAllTypes.getDescriptor(); + FieldDescriptor field = + messageType.findFieldByName("oneof_nested_message"); + OneofDescriptor oneofDescriptor = field.getContainingOneof(); + assertNotNull(oneofDescriptor); + assertSame(oneofDescriptor, messageType.getOneofs().get(0)); + assertEquals("oneof_field", oneofDescriptor.getName()); + + assertEquals(4, oneofDescriptor.getFieldCount()); + assertSame(oneofDescriptor.getField(1), field); + } + + public void testMessageDescriptorExtensions() throws Exception { + assertFalse(TestAllTypes.getDescriptor().isExtendable()); + assertTrue(TestAllExtensions.getDescriptor().isExtendable()); + assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtendable()); + + assertFalse(TestAllTypes.getDescriptor().isExtensionNumber(3)); + assertTrue(TestAllExtensions.getDescriptor().isExtensionNumber(3)); + assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(42)); + assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(43)); + assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4142)); + assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4143)); + } } diff --git a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java index aabccda..ee3769c 100644 --- a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java +++ b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java @@ -30,8 +30,12 @@ package com.google.protobuf; -import protobuf_unittest.UnittestProto.TestAllTypes; +import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.OneofDescriptor; + import protobuf_unittest.UnittestProto.TestAllExtensions; +import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestEmptyMessage; import protobuf_unittest.UnittestProto.TestPackedTypes; import junit.framework.TestCase; @@ -61,28 +65,44 @@ public class DynamicMessageTest extends TestCase { reflectionTester.assertAllFieldsSetViaReflection(message); } - public void testDoubleBuildError() throws Exception { + public void testSettersAfterBuild() throws Exception { Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + Message firstMessage = builder.build(); + // double build() builder.build(); - try { - builder.build(); - fail("Should have thrown exception."); - } catch (IllegalStateException e) { - // Success. - } + // clear() after build() + builder.clear(); + // setters after build() + reflectionTester.setAllFieldsViaReflection(builder); + Message message = builder.build(); + reflectionTester.assertAllFieldsSetViaReflection(message); + // repeated setters after build() + reflectionTester.modifyRepeatedFieldsViaReflection(builder); + message = builder.build(); + reflectionTester.assertRepeatedFieldsModifiedViaReflection(message); + // firstMessage shouldn't have been modified. + reflectionTester.assertClearViaReflection(firstMessage); } - public void testClearAfterBuildError() throws Exception { + public void testUnknownFields() throws Exception { Message.Builder builder = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); - builder.build(); - try { - builder.clear(); - fail("Should have thrown exception."); - } catch (IllegalStateException e) { - // Success. - } + DynamicMessage.newBuilder(TestEmptyMessage.getDescriptor()); + builder.setUnknownFields(UnknownFieldSet.newBuilder() + .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build()) + .addField(2, UnknownFieldSet.Field.newBuilder().addFixed32(1).build()) + .build()); + Message message = builder.build(); + assertEquals(2, message.getUnknownFields().asMap().size()); + // clone() with unknown fields + Message.Builder newBuilder = builder.clone(); + assertEquals(2, newBuilder.getUnknownFields().asMap().size()); + // clear() with unknown fields + newBuilder.clear(); + assertTrue(newBuilder.getUnknownFields().asMap().isEmpty()); + // serialize/parse with unknown fields + newBuilder.mergeFrom(message.toByteString()); + assertEquals(2, newBuilder.getUnknownFields().asMap().size()); } public void testDynamicMessageSettersRejectNull() throws Exception { @@ -167,6 +187,23 @@ public class DynamicMessageTest extends TestCase { Message message2 = DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), rawBytes); reflectionTester.assertAllFieldsSetViaReflection(message2); + + // Test Parser interface. + Message message3 = message2.getParserForType().parseFrom(rawBytes); + reflectionTester.assertAllFieldsSetViaReflection(message3); + } + + public void testDynamicMessageExtensionParsing() throws Exception { + ByteString rawBytes = TestUtil.getAllExtensionsSet().toByteString(); + Message message = DynamicMessage.parseFrom( + TestAllExtensions.getDescriptor(), rawBytes, + TestUtil.getExtensionRegistry()); + extensionsReflectionTester.assertAllFieldsSetViaReflection(message); + + // Test Parser interface. + Message message2 = message.getParserForType().parseFrom( + rawBytes, TestUtil.getExtensionRegistry()); + extensionsReflectionTester.assertAllFieldsSetViaReflection(message2); } public void testDynamicMessagePackedSerialization() throws Exception { @@ -194,6 +231,10 @@ public class DynamicMessageTest extends TestCase { Message message2 = DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes); packedReflectionTester.assertPackedFieldsSetViaReflection(message2); + + // Test Parser interface. + Message message3 = message2.getParserForType().parseFrom(rawBytes); + packedReflectionTester.assertPackedFieldsSetViaReflection(message3); } public void testDynamicMessageCopy() throws Exception { @@ -203,6 +244,19 @@ public class DynamicMessageTest extends TestCase { DynamicMessage copy = DynamicMessage.newBuilder(message).build(); reflectionTester.assertAllFieldsSetViaReflection(copy); + + // Test oneof behavior + FieldDescriptor bytesField = + TestAllTypes.getDescriptor().findFieldByName("oneof_bytes"); + FieldDescriptor uint32Field = + TestAllTypes.getDescriptor().findFieldByName("oneof_uint32"); + assertTrue(copy.hasField(bytesField)); + assertFalse(copy.hasField(uint32Field)); + DynamicMessage copy2 = + DynamicMessage.newBuilder(message).setField(uint32Field, 123).build(); + assertFalse(copy2.hasField(bytesField)); + assertTrue(copy2.hasField(uint32Field)); + assertEquals(123, copy2.getField(uint32Field)); } public void testToBuilder() throws Exception { @@ -223,4 +277,34 @@ public class DynamicMessageTest extends TestCase { assertEquals(Arrays.asList(unknownFieldVal), derived.getUnknownFields().getField(unknownFieldNum).getVarintList()); } + + public void testDynamicOneofMessage() throws Exception { + DynamicMessage.Builder builder = + DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + OneofDescriptor oneof = TestAllTypes.getDescriptor().getOneofs().get(0); + assertFalse(builder.hasOneof(oneof)); + assertSame(null, builder.getOneofFieldDescriptor(oneof)); + + reflectionTester.setAllFieldsViaReflection(builder); + assertTrue(builder.hasOneof(oneof)); + FieldDescriptor field = oneof.getField(3); + assertSame(field, builder.getOneofFieldDescriptor(oneof)); + + DynamicMessage message = builder.buildPartial(); + assertTrue(message.hasOneof(oneof)); + + DynamicMessage.Builder mergedBuilder = + DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + FieldDescriptor mergedField = oneof.getField(0); + mergedBuilder.setField(mergedField, 123); + assertTrue(mergedBuilder.hasField(mergedField)); + mergedBuilder.mergeFrom(message); + assertTrue(mergedBuilder.hasField(field)); + assertFalse(mergedBuilder.hasField(mergedField)); + + builder.clearOneof(oneof); + assertSame(null, builder.getOneofFieldDescriptor(oneof)); + message = builder.build(); + assertSame(null, message.getOneofFieldDescriptor(oneof)); + } } diff --git a/java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java b/java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java new file mode 100644 index 0000000..8b78893 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java @@ -0,0 +1,48 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +/** + * A prerun for a test suite that allows running the full protocol buffer + * tests in a mode that disables the optimization for not using + * {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder} until they are + * requested. This allows us to run all the tests through both code paths + * and ensures that both code paths produce identical results. + * + * @author jonp@google.com (Jon Perlow) + */ +public class ForceFieldBuildersPreRun implements Runnable { + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void run() { + GeneratedMessage.enableAlwaysUseFieldBuildersForTesting(); + } +} diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java index 73c71f3..eb9e632 100644 --- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java +++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java @@ -30,26 +30,51 @@ package com.google.protobuf; +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.UnittestLite.TestAllExtensionsLite; +import com.google.protobuf.test.UnittestImport; +import protobuf_unittest.EnumWithNoOuter; +import protobuf_unittest.MessageWithNoOuter; +import protobuf_unittest.MultipleFilesTestProto; +import protobuf_unittest.NestedExtension.MyNestedExtension; +import protobuf_unittest.NestedExtensionLite.MyNestedExtensionLite; +import protobuf_unittest.NonNestedExtension; +import protobuf_unittest.NonNestedExtension.MessageToBeExtended; +import protobuf_unittest.NonNestedExtension.MyNonNestedExtension; +import protobuf_unittest.NonNestedExtensionLite; +import protobuf_unittest.NonNestedExtensionLite.MessageLiteToBeExtended; +import protobuf_unittest.NonNestedExtensionLite.MyNonNestedExtensionLite; +import protobuf_unittest.OuterClassNameTest2OuterClass; +import protobuf_unittest.OuterClassNameTest3OuterClass; +import protobuf_unittest.OuterClassNameTestOuterClass; +import protobuf_unittest.ServiceWithNoOuter; import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize; import protobuf_unittest.UnittestOptimizeFor.TestOptionalOptimizedForSize; import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize; import protobuf_unittest.UnittestProto; -import protobuf_unittest.UnittestProto.ForeignMessage; import protobuf_unittest.UnittestProto.ForeignEnum; -import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.ForeignMessage; +import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder; import protobuf_unittest.UnittestProto.TestAllExtensions; +import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage; +import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder; import protobuf_unittest.UnittestProto.TestExtremeDefaultValues; +import protobuf_unittest.UnittestProto.TestOneof2; import protobuf_unittest.UnittestProto.TestPackedTypes; import protobuf_unittest.UnittestProto.TestUnpackedTypes; -import protobuf_unittest.MultipleFilesTestProto; -import protobuf_unittest.MessageWithNoOuter; -import protobuf_unittest.EnumWithNoOuter; -import protobuf_unittest.ServiceWithNoOuter; -import com.google.protobuf.UnittestLite; -import com.google.protobuf.UnittestLite.TestAllExtensionsLite; import junit.framework.TestCase; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; /** * Unit test for generated messages and generated code. See also @@ -68,32 +93,138 @@ public class GeneratedMessageTest extends TestCase { TestAllTypes.newBuilder().getDefaultInstanceForType()); } - public void testAccessors() throws Exception { + public void testMessageOrBuilder() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TestUtil.setAllFields(builder); TestAllTypes message = builder.build(); TestUtil.assertAllFieldsSet(message); } - public void testDoubleBuildError() throws Exception { + public void testUsingBuilderMultipleTimes() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - builder.build(); - try { - builder.build(); - fail("Should have thrown exception."); - } catch (IllegalStateException e) { - // Success. - } + // primitive field scalar and repeated + builder.setOptionalSfixed64(100); + builder.addRepeatedInt32(100); + // enum field scalar and repeated + builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_BAR); + builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR); + // proto field scalar and repeated + builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(1)); + builder.addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(1)); + + TestAllTypes value1 = builder.build(); + + assertEquals(100, value1.getOptionalSfixed64()); + assertEquals(100, value1.getRepeatedInt32(0)); + assertEquals(UnittestImport.ImportEnum.IMPORT_BAR, + value1.getOptionalImportEnum()); + assertEquals(UnittestImport.ImportEnum.IMPORT_BAR, + value1.getRepeatedImportEnum(0)); + assertEquals(1, value1.getOptionalForeignMessage().getC()); + assertEquals(1, value1.getRepeatedForeignMessage(0).getC()); + + // Make sure that builder didn't update previously created values + builder.setOptionalSfixed64(200); + builder.setRepeatedInt32(0, 200); + builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_FOO); + builder.setRepeatedImportEnum(0, UnittestImport.ImportEnum.IMPORT_FOO); + builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(2)); + builder.setRepeatedForeignMessage(0, ForeignMessage.newBuilder().setC(2)); + + TestAllTypes value2 = builder.build(); + + // Make sure value1 didn't change. + assertEquals(100, value1.getOptionalSfixed64()); + assertEquals(100, value1.getRepeatedInt32(0)); + assertEquals(UnittestImport.ImportEnum.IMPORT_BAR, + value1.getOptionalImportEnum()); + assertEquals(UnittestImport.ImportEnum.IMPORT_BAR, + value1.getRepeatedImportEnum(0)); + assertEquals(1, value1.getOptionalForeignMessage().getC()); + assertEquals(1, value1.getRepeatedForeignMessage(0).getC()); + + // Make sure value2 is correct + assertEquals(200, value2.getOptionalSfixed64()); + assertEquals(200, value2.getRepeatedInt32(0)); + assertEquals(UnittestImport.ImportEnum.IMPORT_FOO, + value2.getOptionalImportEnum()); + assertEquals(UnittestImport.ImportEnum.IMPORT_FOO, + value2.getRepeatedImportEnum(0)); + assertEquals(2, value2.getOptionalForeignMessage().getC()); + assertEquals(2, value2.getRepeatedForeignMessage(0).getC()); } - public void testClearAfterBuildError() throws Exception { + public void testProtosShareRepeatedArraysIfDidntChange() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - builder.build(); - try { - builder.clear(); - fail("Should have thrown exception."); - } catch (IllegalStateException e) { - // Success. + builder.addRepeatedInt32(100); + builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR); + builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance()); + + TestAllTypes value1 = builder.build(); + TestAllTypes value2 = value1.toBuilder().build(); + + assertSame(value1.getRepeatedInt32List(), value2.getRepeatedInt32List()); + assertSame(value1.getRepeatedImportEnumList(), + value2.getRepeatedImportEnumList()); + assertSame(value1.getRepeatedForeignMessageList(), + value2.getRepeatedForeignMessageList()); + } + + public void testRepeatedArraysAreImmutable() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + builder.addRepeatedInt32(100); + builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR); + builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance()); + assertIsUnmodifiable(builder.getRepeatedInt32List()); + assertIsUnmodifiable(builder.getRepeatedImportEnumList()); + assertIsUnmodifiable(builder.getRepeatedForeignMessageList()); + assertIsUnmodifiable(builder.getRepeatedFloatList()); + + + TestAllTypes value = builder.build(); + assertIsUnmodifiable(value.getRepeatedInt32List()); + assertIsUnmodifiable(value.getRepeatedImportEnumList()); + assertIsUnmodifiable(value.getRepeatedForeignMessageList()); + assertIsUnmodifiable(value.getRepeatedFloatList()); + } + + public void testParsedMessagesAreImmutable() throws Exception { + TestAllTypes value = TestAllTypes.PARSER.parseFrom( + TestUtil.getAllSet().toByteString()); + assertIsUnmodifiable(value.getRepeatedInt32List()); + assertIsUnmodifiable(value.getRepeatedInt64List()); + assertIsUnmodifiable(value.getRepeatedUint32List()); + assertIsUnmodifiable(value.getRepeatedUint64List()); + assertIsUnmodifiable(value.getRepeatedSint32List()); + assertIsUnmodifiable(value.getRepeatedSint64List()); + assertIsUnmodifiable(value.getRepeatedFixed32List()); + assertIsUnmodifiable(value.getRepeatedFixed64List()); + assertIsUnmodifiable(value.getRepeatedSfixed32List()); + assertIsUnmodifiable(value.getRepeatedSfixed64List()); + assertIsUnmodifiable(value.getRepeatedFloatList()); + assertIsUnmodifiable(value.getRepeatedDoubleList()); + assertIsUnmodifiable(value.getRepeatedBoolList()); + assertIsUnmodifiable(value.getRepeatedStringList()); + assertIsUnmodifiable(value.getRepeatedBytesList()); + assertIsUnmodifiable(value.getRepeatedGroupList()); + assertIsUnmodifiable(value.getRepeatedNestedMessageList()); + assertIsUnmodifiable(value.getRepeatedForeignMessageList()); + assertIsUnmodifiable(value.getRepeatedImportMessageList()); + assertIsUnmodifiable(value.getRepeatedNestedEnumList()); + assertIsUnmodifiable(value.getRepeatedForeignEnumList()); + assertIsUnmodifiable(value.getRepeatedImportEnumList()); + } + + private void assertIsUnmodifiable(List list) { + if (list == Collections.emptyList()) { + // OKAY -- Need to check this b/c EmptyList allows you to call clear. + } else { + try { + list.clear(); + fail("List wasn't immutable"); + } catch (UnsupportedOperationException e) { + // good + } } } @@ -273,6 +404,44 @@ public class GeneratedMessageTest extends TestCase { // We expect this exception. } } + + public void testRepeatedAppendIterateOnlyOnce() throws Exception { + // Create a Iterable that can only be iterated once. + Iterable stringIterable = new Iterable() { + private boolean called = false; + @Override + public Iterator iterator() { + if (called) { + throw new IllegalStateException(); + } + called = true; + return Arrays.asList("one", "two", "three").iterator(); + } + }; + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + builder.addAllRepeatedString(stringIterable); + assertEquals(3, builder.getRepeatedStringCount()); + assertEquals("one", builder.getRepeatedString(0)); + assertEquals("two", builder.getRepeatedString(1)); + assertEquals("three", builder.getRepeatedString(2)); + + try { + builder.addAllRepeatedString(stringIterable); + fail("Exception was not thrown"); + } catch (IllegalStateException e) { + // We expect this exception. + } + } + + public void testMergeFromOtherRejectsNull() throws Exception { + try { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + builder.mergeFrom((TestAllTypes) null); + fail("Exception was not thrown"); + } catch (NullPointerException e) { + // We expect this exception. + } + } public void testSettingForeignMessageUsingBuilder() throws Exception { TestAllTypes message = TestAllTypes.newBuilder() @@ -314,11 +483,22 @@ public class GeneratedMessageTest extends TestCase { assertEquals(Float.POSITIVE_INFINITY, message.getInfFloat()); assertEquals(Float.NEGATIVE_INFINITY, message.getNegInfFloat()); assertTrue(Float.isNaN(message.getNanFloat())); + assertEquals("? ? ?? ?? ??? ??/ ??-", message.getCppTrigraph()); + } + + public void testClear() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + TestUtil.assertClear(builder); + TestUtil.setAllFields(builder); + builder.clear(); + TestUtil.assertClear(builder); } public void testReflectionGetters() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TestUtil.setAllFields(builder); + reflectionTester.assertAllFieldsSetViaReflection(builder); + TestAllTypes message = builder.build(); reflectionTester.assertAllFieldsSetViaReflection(message); } @@ -326,6 +506,8 @@ public class GeneratedMessageTest extends TestCase { public void testReflectionSetters() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); reflectionTester.setAllFieldsViaReflection(builder); + TestUtil.assertAllFieldsSet(builder); + TestAllTypes message = builder.build(); TestUtil.assertAllFieldsSet(message); } @@ -339,6 +521,8 @@ public class GeneratedMessageTest extends TestCase { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); reflectionTester.setAllFieldsViaReflection(builder); reflectionTester.modifyRepeatedFieldsViaReflection(builder); + TestUtil.assertRepeatedFieldsModified(builder); + TestAllTypes message = builder.build(); TestUtil.assertRepeatedFieldsModified(message); } @@ -355,6 +539,34 @@ public class GeneratedMessageTest extends TestCase { TestAllTypes.newBuilder().build()); } + public void testReflectionGetOneof() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + reflectionTester.setAllFieldsViaReflection(builder); + Descriptors.OneofDescriptor oneof = + TestAllTypes.getDescriptor().getOneofs().get(0); + Descriptors.FieldDescriptor field = + TestAllTypes.getDescriptor().findFieldByName("oneof_bytes"); + assertSame(field, builder.getOneofFieldDescriptor(oneof)); + + TestAllTypes message = builder.build(); + assertSame(field, message.getOneofFieldDescriptor(oneof)); + } + + public void testReflectionClearOneof() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + reflectionTester.setAllFieldsViaReflection(builder); + Descriptors.OneofDescriptor oneof = + TestAllTypes.getDescriptor().getOneofs().get(0); + Descriptors.FieldDescriptor field = + TestAllTypes.getDescriptor().findFieldByName("oneof_bytes"); + + assertTrue(builder.hasOneof(oneof)); + assertTrue(builder.hasField(field)); + builder.clearOneof(oneof); + assertFalse(builder.hasOneof(oneof)); + assertFalse(builder.hasField(field)); + } + public void testEnumInterface() throws Exception { assertTrue(TestAllTypes.getDefaultInstance().getDefaultNestedEnum() instanceof ProtocolMessageEnum); @@ -391,7 +603,7 @@ public class GeneratedMessageTest extends TestCase { new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(), TestUtil.getExtensionRegistry()); - public void testExtensionAccessors() throws Exception { + public void testExtensionMessageOrBuilder() throws Exception { TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); TestUtil.setAllExtensions(builder); TestAllExtensions message = builder.build(); @@ -414,6 +626,8 @@ public class GeneratedMessageTest extends TestCase { public void testExtensionReflectionGetters() throws Exception { TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); TestUtil.setAllExtensions(builder); + extensionsReflectionTester.assertAllFieldsSetViaReflection(builder); + TestAllExtensions message = builder.build(); extensionsReflectionTester.assertAllFieldsSetViaReflection(message); } @@ -421,6 +635,8 @@ public class GeneratedMessageTest extends TestCase { public void testExtensionReflectionSetters() throws Exception { TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); extensionsReflectionTester.setAllFieldsViaReflection(builder); + TestUtil.assertAllExtensionsSet(builder); + TestAllExtensions message = builder.build(); TestUtil.assertAllExtensionsSet(message); } @@ -434,6 +650,8 @@ public class GeneratedMessageTest extends TestCase { TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); extensionsReflectionTester.setAllFieldsViaReflection(builder); extensionsReflectionTester.modifyRepeatedFieldsViaReflection(builder); + TestUtil.assertRepeatedExtensionsModified(builder); + TestAllExtensions message = builder.build(); TestUtil.assertRepeatedExtensionsModified(message); } @@ -491,9 +709,11 @@ public class GeneratedMessageTest extends TestCase { // lite fields directly since they are implemented exactly the same as // regular fields. - public void testLiteExtensionAccessors() throws Exception { + public void testLiteExtensionMessageOrBuilder() throws Exception { TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder(); TestUtil.setAllExtensions(builder); + TestUtil.assertAllExtensionsSet(builder); + TestAllExtensionsLite message = builder.build(); TestUtil.assertAllExtensionsSet(message); } @@ -502,6 +722,8 @@ public class GeneratedMessageTest extends TestCase { TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder(); TestUtil.setAllExtensions(builder); TestUtil.modifyRepeatedExtensions(builder); + TestUtil.assertRepeatedExtensionsModified(builder); + TestAllExtensionsLite message = builder.build(); TestUtil.assertRepeatedExtensionsModified(message); } @@ -546,6 +768,15 @@ public class GeneratedMessageTest extends TestCase { // ================================================================= // multiple_files_test + // Test that custom options of an file level enum are properly initialized. + // This test needs to be put before any other access to MultipleFilesTestProto + // or messages defined in multiple_files_test.proto because the class loading + // order affects initialization process of custom options. + public void testEnumValueOptionsInMultipleFilesMode() throws Exception { + assertEquals(12345, EnumWithNoOuter.FOO.getValueDescriptor().getOptions() + .getExtension(MultipleFilesTestProto.enumValueOption).intValue()); + } + public void testMultipleFilesOption() throws Exception { // We mostly just want to check that things compile. MessageWithNoOuter message = @@ -609,6 +840,7 @@ public class GeneratedMessageTest extends TestCase { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TestUtil.setAllFields(builder); TestAllTypes message = builder.build(); + TestUtil.assertAllFieldsSet(message); TestUtil.assertAllFieldsSet(message.toBuilder().build()); } @@ -643,7 +875,641 @@ public class GeneratedMessageTest extends TestCase { UnittestProto.TestRecursiveMessage message = UnittestProto.TestRecursiveMessage.getDefaultInstance(); assertTrue(message != null); - assertTrue(message.getA() != null); + assertNotNull(message.getA()); assertTrue(message.getA() == message); } + + public void testSerialize() throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + TestUtil.setAllFields(builder); + TestAllTypes expected = builder.build(); + ObjectOutputStream out = new ObjectOutputStream(baos); + try { + out.writeObject(expected); + } finally { + out.close(); + } + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream in = new ObjectInputStream(bais); + TestAllTypes actual = (TestAllTypes) in.readObject(); + assertEquals(expected, actual); + } + + public void testSerializePartial() throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + TestAllTypes expected = builder.buildPartial(); + ObjectOutputStream out = new ObjectOutputStream(baos); + try { + out.writeObject(expected); + } finally { + out.close(); + } + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream in = new ObjectInputStream(bais); + TestAllTypes actual = (TestAllTypes) in.readObject(); + assertEquals(expected, actual); + } + + public void testEnumValues() { + assertEquals( + TestAllTypes.NestedEnum.BAR.getNumber(), + TestAllTypes.NestedEnum.BAR_VALUE); + assertEquals( + TestAllTypes.NestedEnum.BAZ.getNumber(), + TestAllTypes.NestedEnum.BAZ_VALUE); + assertEquals( + TestAllTypes.NestedEnum.FOO.getNumber(), + TestAllTypes.NestedEnum.FOO_VALUE); + } + + public void testNonNestedExtensionInitialization() { + assertTrue(NonNestedExtension.nonNestedExtension + .getMessageDefaultInstance() instanceof MyNonNestedExtension); + assertEquals("nonNestedExtension", + NonNestedExtension.nonNestedExtension.getDescriptor().getName()); + } + + public void testNestedExtensionInitialization() { + assertTrue(MyNestedExtension.recursiveExtension.getMessageDefaultInstance() + instanceof MessageToBeExtended); + assertEquals("recursiveExtension", + MyNestedExtension.recursiveExtension.getDescriptor().getName()); + } + + public void testNonNestedExtensionLiteInitialization() { + assertTrue(NonNestedExtensionLite.nonNestedExtensionLite + .getMessageDefaultInstance() instanceof MyNonNestedExtensionLite); + } + + public void testNestedExtensionLiteInitialization() { + assertTrue(MyNestedExtensionLite.recursiveExtensionLite + .getMessageDefaultInstance() instanceof MessageLiteToBeExtended); + } + + public void testInvalidations() throws Exception { + GeneratedMessage.enableAlwaysUseFieldBuildersForTesting(); + TestAllTypes.NestedMessage nestedMessage1 = + TestAllTypes.NestedMessage.newBuilder().build(); + TestAllTypes.NestedMessage nestedMessage2 = + TestAllTypes.NestedMessage.newBuilder().build(); + + // Set all three flavors (enum, primitive, message and singular/repeated) + // and verify no invalidations fired + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + + TestAllTypes.Builder builder = (TestAllTypes.Builder) + ((GeneratedMessage) TestAllTypes.getDefaultInstance()). + newBuilderForType(mockParent); + builder.setOptionalInt32(1); + builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR); + builder.setOptionalNestedMessage(nestedMessage1); + builder.addRepeatedInt32(1); + builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR); + builder.addRepeatedNestedMessage(nestedMessage1); + assertEquals(0, mockParent.getInvalidationCount()); + + // Now tell it we want changes and make sure it's only fired once + // And do this for each flavor + + // primitive single + builder.buildPartial(); + builder.setOptionalInt32(2); + builder.setOptionalInt32(3); + assertEquals(1, mockParent.getInvalidationCount()); + + // enum single + builder.buildPartial(); + builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAZ); + builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR); + assertEquals(2, mockParent.getInvalidationCount()); + + // message single + builder.buildPartial(); + builder.setOptionalNestedMessage(nestedMessage2); + builder.setOptionalNestedMessage(nestedMessage1); + assertEquals(3, mockParent.getInvalidationCount()); + + // primitive repeated + builder.buildPartial(); + builder.addRepeatedInt32(2); + builder.addRepeatedInt32(3); + assertEquals(4, mockParent.getInvalidationCount()); + + // enum repeated + builder.buildPartial(); + builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ); + builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ); + assertEquals(5, mockParent.getInvalidationCount()); + + // message repeated + builder.buildPartial(); + builder.addRepeatedNestedMessage(nestedMessage2); + builder.addRepeatedNestedMessage(nestedMessage1); + assertEquals(6, mockParent.getInvalidationCount()); + + } + + public void testInvalidations_Extensions() throws Exception { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + + TestAllExtensions.Builder builder = (TestAllExtensions.Builder) + ((GeneratedMessage) TestAllExtensions.getDefaultInstance()). + newBuilderForType(mockParent); + + builder.addExtension(UnittestProto.repeatedInt32Extension, 1); + builder.setExtension(UnittestProto.repeatedInt32Extension, 0, 2); + builder.clearExtension(UnittestProto.repeatedInt32Extension); + assertEquals(0, mockParent.getInvalidationCount()); + + // Now tell it we want changes and make sure it's only fired once + builder.buildPartial(); + builder.addExtension(UnittestProto.repeatedInt32Extension, 2); + builder.addExtension(UnittestProto.repeatedInt32Extension, 3); + assertEquals(1, mockParent.getInvalidationCount()); + + builder.buildPartial(); + builder.setExtension(UnittestProto.repeatedInt32Extension, 0, 4); + builder.setExtension(UnittestProto.repeatedInt32Extension, 1, 5); + assertEquals(2, mockParent.getInvalidationCount()); + + builder.buildPartial(); + builder.clearExtension(UnittestProto.repeatedInt32Extension); + builder.clearExtension(UnittestProto.repeatedInt32Extension); + assertEquals(3, mockParent.getInvalidationCount()); + } + + public void testBaseMessageOrBuilder() { + // Mostly just makes sure the base interface exists and has some methods. + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + TestAllTypes message = builder.buildPartial(); + TestAllTypesOrBuilder builderAsInterface = (TestAllTypesOrBuilder) builder; + TestAllTypesOrBuilder messageAsInterface = (TestAllTypesOrBuilder) message; + + assertEquals( + messageAsInterface.getDefaultBool(), + messageAsInterface.getDefaultBool()); + assertEquals( + messageAsInterface.getOptionalDouble(), + messageAsInterface.getOptionalDouble()); + } + + public void testMessageOrBuilderGetters() { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + + // single fields + assertSame(ForeignMessage.getDefaultInstance(), + builder.getOptionalForeignMessageOrBuilder()); + ForeignMessage.Builder subBuilder = + builder.getOptionalForeignMessageBuilder(); + assertSame(subBuilder, builder.getOptionalForeignMessageOrBuilder()); + + // repeated fields + ForeignMessage m0 = ForeignMessage.newBuilder().buildPartial(); + ForeignMessage m1 = ForeignMessage.newBuilder().buildPartial(); + ForeignMessage m2 = ForeignMessage.newBuilder().buildPartial(); + builder.addRepeatedForeignMessage(m0); + builder.addRepeatedForeignMessage(m1); + builder.addRepeatedForeignMessage(m2); + assertSame(m0, builder.getRepeatedForeignMessageOrBuilder(0)); + assertSame(m1, builder.getRepeatedForeignMessageOrBuilder(1)); + assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2)); + ForeignMessage.Builder b0 = builder.getRepeatedForeignMessageBuilder(0); + ForeignMessage.Builder b1 = builder.getRepeatedForeignMessageBuilder(1); + assertSame(b0, builder.getRepeatedForeignMessageOrBuilder(0)); + assertSame(b1, builder.getRepeatedForeignMessageOrBuilder(1)); + assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2)); + + List messageOrBuilderList = + builder.getRepeatedForeignMessageOrBuilderList(); + assertSame(b0, messageOrBuilderList.get(0)); + assertSame(b1, messageOrBuilderList.get(1)); + assertSame(m2, messageOrBuilderList.get(2)); + } + + public void testGetFieldBuilder() { + Descriptor descriptor = TestAllTypes.getDescriptor(); + + FieldDescriptor fieldDescriptor = + descriptor.findFieldByName("optional_nested_message"); + FieldDescriptor foreignFieldDescriptor = + descriptor.findFieldByName("optional_foreign_message"); + FieldDescriptor importFieldDescriptor = + descriptor.findFieldByName("optional_import_message"); + + // Mutate the message with new field builder + // Mutate nested message + TestAllTypes.Builder builder1 = TestAllTypes.newBuilder(); + Message.Builder fieldBuilder1 = builder1.newBuilderForField(fieldDescriptor) + .mergeFrom((Message) builder1.getField(fieldDescriptor)); + FieldDescriptor subFieldDescriptor1 = + fieldBuilder1.getDescriptorForType().findFieldByName("bb"); + fieldBuilder1.setField(subFieldDescriptor1, 1); + builder1.setField(fieldDescriptor, fieldBuilder1.build()); + + // Mutate foreign message + Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField( + foreignFieldDescriptor) + .mergeFrom((Message) builder1.getField(foreignFieldDescriptor)); + FieldDescriptor subForeignFieldDescriptor1 = + foreignFieldBuilder1.getDescriptorForType().findFieldByName("c"); + foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2); + builder1.setField(foreignFieldDescriptor, foreignFieldBuilder1.build()); + + // Mutate import message + Message.Builder importFieldBuilder1 = builder1.newBuilderForField( + importFieldDescriptor) + .mergeFrom((Message) builder1.getField(importFieldDescriptor)); + FieldDescriptor subImportFieldDescriptor1 = + importFieldBuilder1.getDescriptorForType().findFieldByName("d"); + importFieldBuilder1.setField(subImportFieldDescriptor1, 3); + builder1.setField(importFieldDescriptor, importFieldBuilder1.build()); + + Message newMessage1 = builder1.build(); + + // Mutate the message with existing field builder + // Mutate nested message + TestAllTypes.Builder builder2 = TestAllTypes.newBuilder(); + Message.Builder fieldBuilder2 = builder2.getFieldBuilder(fieldDescriptor); + FieldDescriptor subFieldDescriptor2 = + fieldBuilder2.getDescriptorForType().findFieldByName("bb"); + fieldBuilder2.setField(subFieldDescriptor2, 1); + builder2.setField(fieldDescriptor, fieldBuilder2.build()); + + // Mutate foreign message + Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField( + foreignFieldDescriptor) + .mergeFrom((Message) builder2.getField(foreignFieldDescriptor)); + FieldDescriptor subForeignFieldDescriptor2 = + foreignFieldBuilder2.getDescriptorForType().findFieldByName("c"); + foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2); + builder2.setField(foreignFieldDescriptor, foreignFieldBuilder2.build()); + + // Mutate import message + Message.Builder importFieldBuilder2 = builder2.newBuilderForField( + importFieldDescriptor) + .mergeFrom((Message) builder2.getField(importFieldDescriptor)); + FieldDescriptor subImportFieldDescriptor2 = + importFieldBuilder2.getDescriptorForType().findFieldByName("d"); + importFieldBuilder2.setField(subImportFieldDescriptor2, 3); + builder2.setField(importFieldDescriptor, importFieldBuilder2.build()); + + Message newMessage2 = builder2.build(); + + // These two messages should be equal. + assertEquals(newMessage1, newMessage2); + } + + public void testGetFieldBuilderWithInitializedValue() { + Descriptor descriptor = TestAllTypes.getDescriptor(); + FieldDescriptor fieldDescriptor = + descriptor.findFieldByName("optional_nested_message"); + + // Before setting field, builder is initialized by default value. + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + NestedMessage.Builder fieldBuilder = + (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor); + assertEquals(0, fieldBuilder.getBb()); + + // Setting field value with new field builder instance. + builder = TestAllTypes.newBuilder(); + NestedMessage.Builder newFieldBuilder = + builder.getOptionalNestedMessageBuilder(); + newFieldBuilder.setBb(2); + // Then get the field builder instance by getFieldBuilder(). + fieldBuilder = + (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor); + // It should contain new value. + assertEquals(2, fieldBuilder.getBb()); + // These two builder should be equal. + assertSame(fieldBuilder, newFieldBuilder); + } + + public void testGetFieldBuilderNotSupportedException() { + Descriptor descriptor = TestAllTypes.getDescriptor(); + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + try { + builder.getFieldBuilder(descriptor.findFieldByName("optional_int32")); + fail("Exception was not thrown"); + } catch (UnsupportedOperationException e) { + // We expect this exception. + } + try { + builder.getFieldBuilder( + descriptor.findFieldByName("optional_nested_enum")); + fail("Exception was not thrown"); + } catch (UnsupportedOperationException e) { + // We expect this exception. + } + try { + builder.getFieldBuilder(descriptor.findFieldByName("repeated_int32")); + fail("Exception was not thrown"); + } catch (UnsupportedOperationException e) { + // We expect this exception. + } + try { + builder.getFieldBuilder( + descriptor.findFieldByName("repeated_nested_enum")); + fail("Exception was not thrown"); + } catch (UnsupportedOperationException e) { + // We expect this exception. + } + try { + builder.getFieldBuilder( + descriptor.findFieldByName("repeated_nested_message")); + fail("Exception was not thrown"); + } catch (UnsupportedOperationException e) { + // We expect this exception. + } + } + + // Test that when the default outer class name conflicts with another type + // defined in the proto the compiler will append a suffix to avoid the + // conflict. + public void testConflictingOuterClassName() { + // We just need to make sure we can refer to the outer class with the + // expected name. There is nothing else to test. + OuterClassNameTestOuterClass.OuterClassNameTest message = + OuterClassNameTestOuterClass.OuterClassNameTest.newBuilder().build(); + assertTrue(message.getDescriptorForType() == + OuterClassNameTestOuterClass.OuterClassNameTest.getDescriptor()); + + OuterClassNameTest2OuterClass.TestMessage2.NestedMessage.OuterClassNameTest2 + message2 = OuterClassNameTest2OuterClass.TestMessage2.NestedMessage + .OuterClassNameTest2.newBuilder().build(); + assertEquals(0, message2.getSerializedSize()); + + OuterClassNameTest3OuterClass.TestMessage3.NestedMessage.OuterClassNameTest3 + enumValue = OuterClassNameTest3OuterClass.TestMessage3.NestedMessage + .OuterClassNameTest3.DUMMY_VALUE; + assertEquals(1, enumValue.getNumber()); + } + + // ================================================================= + // oneof generated code test + public void testOneofEnumCase() throws Exception { + TestOneof2 message = TestOneof2.newBuilder() + .setFooInt(123).setFooString("foo").setFooCord("bar").build(); + TestUtil.assertAtMostOneFieldSetOneof(message); + } + + public void testClearOneof() throws Exception { + TestOneof2.Builder builder = TestOneof2.newBuilder().setFooInt(123); + assertEquals(TestOneof2.FooCase.FOO_INT, builder.getFooCase()); + builder.clearFoo(); + assertEquals(TestOneof2.FooCase.FOO_NOT_SET, builder.getFooCase()); + } + + public void testSetOneofClearsOthers() throws Exception { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + TestOneof2 message = + builder.setFooInt(123).setFooString("foo").buildPartial(); + assertTrue(message.hasFooString()); + TestUtil.assertAtMostOneFieldSetOneof(message); + + message = builder.setFooCord("bar").buildPartial(); + assertTrue(message.hasFooCord()); + TestUtil.assertAtMostOneFieldSetOneof(message); + + message = builder.setFooStringPiece("baz").buildPartial(); + assertTrue(message.hasFooStringPiece()); + TestUtil.assertAtMostOneFieldSetOneof(message); + + message = builder.setFooBytes(TestUtil.toBytes("qux")).buildPartial(); + assertTrue(message.hasFooBytes()); + TestUtil.assertAtMostOneFieldSetOneof(message); + + message = builder.setFooEnum(TestOneof2.NestedEnum.FOO).buildPartial(); + assertTrue(message.hasFooEnum()); + TestUtil.assertAtMostOneFieldSetOneof(message); + + message = builder.setFooMessage( + TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).buildPartial(); + assertTrue(message.hasFooMessage()); + TestUtil.assertAtMostOneFieldSetOneof(message); + + message = builder.setFooInt(123).buildPartial(); + assertTrue(message.hasFooInt()); + TestUtil.assertAtMostOneFieldSetOneof(message); + } + + public void testOneofTypes() throws Exception { + // Primitive + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + assertEquals(builder.getFooInt(), 0); + assertFalse(builder.hasFooInt()); + assertTrue(builder.setFooInt(123).hasFooInt()); + assertEquals(builder.getFooInt(), 123); + TestOneof2 message = builder.buildPartial(); + assertTrue(message.hasFooInt()); + assertEquals(message.getFooInt(), 123); + + assertFalse(builder.clearFooInt().hasFooInt()); + TestOneof2 message2 = builder.build(); + assertFalse(message2.hasFooInt()); + assertEquals(message2.getFooInt(), 0); + } + + // Enum + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + assertEquals(builder.getFooEnum(), TestOneof2.NestedEnum.FOO); + assertTrue(builder.setFooEnum(TestOneof2.NestedEnum.BAR).hasFooEnum()); + assertEquals(builder.getFooEnum(), TestOneof2.NestedEnum.BAR); + TestOneof2 message = builder.buildPartial(); + assertTrue(message.hasFooEnum()); + assertEquals(message.getFooEnum(), TestOneof2.NestedEnum.BAR); + + assertFalse(builder.clearFooEnum().hasFooEnum()); + TestOneof2 message2 = builder.build(); + assertFalse(message2.hasFooEnum()); + assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.FOO); + } + + // String + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + assertEquals(builder.getFooString(), ""); + builder.setFooString("foo"); + assertTrue(builder.hasFooString()); + assertEquals(builder.getFooString(), "foo"); + TestOneof2 message = builder.buildPartial(); + assertTrue(message.hasFooString()); + assertEquals(message.getFooString(), "foo"); + assertEquals(message.getFooStringBytes(), TestUtil.toBytes("foo")); + + assertFalse(builder.clearFooString().hasFooString()); + TestOneof2 message2 = builder.buildPartial(); + assertFalse(message2.hasFooString()); + assertEquals(message2.getFooString(), ""); + assertEquals(message2.getFooStringBytes(), TestUtil.toBytes("")); + + // Get method should not change the oneof value. + builder.setFooInt(123); + assertEquals(builder.getFooString(), ""); + assertEquals(builder.getFooStringBytes(), TestUtil.toBytes("")); + assertEquals(123, builder.getFooInt()); + + message = builder.build(); + assertEquals(message.getFooString(), ""); + assertEquals(message.getFooStringBytes(), TestUtil.toBytes("")); + assertEquals(123, message.getFooInt()); + } + + // Cord + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + assertEquals(builder.getFooCord(), ""); + builder.setFooCord("foo"); + assertTrue(builder.hasFooCord()); + assertEquals(builder.getFooCord(), "foo"); + TestOneof2 message = builder.buildPartial(); + assertTrue(message.hasFooCord()); + assertEquals(message.getFooCord(), "foo"); + assertEquals(message.getFooCordBytes(), TestUtil.toBytes("foo")); + + assertFalse(builder.clearFooCord().hasFooCord()); + TestOneof2 message2 = builder.build(); + assertFalse(message2.hasFooCord()); + assertEquals(message2.getFooCord(), ""); + assertEquals(message2.getFooCordBytes(), TestUtil.toBytes("")); + } + + // StringPiece + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + assertEquals(builder.getFooStringPiece(), ""); + builder.setFooStringPiece("foo"); + assertTrue(builder.hasFooStringPiece()); + assertEquals(builder.getFooStringPiece(), "foo"); + TestOneof2 message = builder.buildPartial(); + assertTrue(message.hasFooStringPiece()); + assertEquals(message.getFooStringPiece(), "foo"); + assertEquals(message.getFooStringPieceBytes(), TestUtil.toBytes("foo")); + + assertFalse(builder.clearFooStringPiece().hasFooStringPiece()); + TestOneof2 message2 = builder.build(); + assertFalse(message2.hasFooStringPiece()); + assertEquals(message2.getFooStringPiece(), ""); + assertEquals(message2.getFooStringPieceBytes(), TestUtil.toBytes("")); + } + + // Message + { + // set + TestOneof2.Builder builder = TestOneof2.newBuilder(); + assertEquals(builder.getFooMessage().getQuxInt(), 0); + builder.setFooMessage( + TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()); + assertTrue(builder.hasFooMessage()); + assertEquals(builder.getFooMessage().getQuxInt(), 234); + TestOneof2 message = builder.buildPartial(); + assertTrue(message.hasFooMessage()); + assertEquals(message.getFooMessage().getQuxInt(), 234); + + // clear + assertFalse(builder.clearFooMessage().hasFooString()); + message = builder.build(); + assertFalse(message.hasFooMessage()); + assertEquals(message.getFooMessage().getQuxInt(), 0); + + // nested builder + builder = TestOneof2.newBuilder(); + assertSame(builder.getFooMessageOrBuilder(), + TestOneof2.NestedMessage.getDefaultInstance()); + assertFalse(builder.hasFooMessage()); + builder.getFooMessageBuilder().setQuxInt(123); + assertTrue(builder.hasFooMessage()); + assertEquals(builder.getFooMessage().getQuxInt(), 123); + message = builder.build(); + assertTrue(message.hasFooMessage()); + assertEquals(message.getFooMessage().getQuxInt(), 123); + } + + // LazyMessage is tested in LazyMessageLiteTest.java + } + + public void testOneofMerge() throws Exception { + // Primitive Type + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + TestOneof2 message = builder.setFooInt(123).build(); + TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build(); + assertTrue(message2.hasFooInt()); + assertEquals(message2.getFooInt(), 123); + } + + // String + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + TestOneof2 message = builder.setFooString("foo").build(); + TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build(); + assertTrue(message2.hasFooString()); + assertEquals(message2.getFooString(), "foo"); + } + + // Enum + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + TestOneof2 message = builder.setFooEnum(TestOneof2.NestedEnum.BAR).build(); + TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build(); + assertTrue(message2.hasFooEnum()); + assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.BAR); + } + + // Message + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + TestOneof2 message = builder.setFooMessage( + TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build(); + TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build(); + assertTrue(message2.hasFooMessage()); + assertEquals(message2.getFooMessage().getQuxInt(), 234); + } + } + + public void testOneofSerialization() throws Exception { + // Primitive Type + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + TestOneof2 message = builder.setFooInt(123).build(); + ByteString serialized = message.toByteString(); + TestOneof2 message2 = TestOneof2.parseFrom(serialized); + assertTrue(message2.hasFooInt()); + assertEquals(message2.getFooInt(), 123); + } + + // String + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + TestOneof2 message = builder.setFooString("foo").build(); + ByteString serialized = message.toByteString(); + TestOneof2 message2 = TestOneof2.parseFrom(serialized); + assertTrue(message2.hasFooString()); + assertEquals(message2.getFooString(), "foo"); + } + + // Enum + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + TestOneof2 message = builder.setFooEnum(TestOneof2.NestedEnum.BAR).build(); + ByteString serialized = message.toByteString(); + TestOneof2 message2 = TestOneof2.parseFrom(serialized); + assertTrue(message2.hasFooEnum()); + assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.BAR); + } + + // Message + { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + TestOneof2 message = builder.setFooMessage( + TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build(); + ByteString serialized = message.toByteString(); + TestOneof2 message2 = TestOneof2.parseFrom(serialized); + assertTrue(message2.hasFooMessage()); + assertEquals(message2.getFooMessage().getQuxInt(), 234); + } + } } diff --git a/java/src/test/java/com/google/protobuf/IsValidUtf8Test.java b/java/src/test/java/com/google/protobuf/IsValidUtf8Test.java new file mode 100644 index 0000000..b204b60 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/IsValidUtf8Test.java @@ -0,0 +1,180 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import com.google.protobuf.IsValidUtf8TestUtil.Shard; + +import junit.framework.TestCase; + +import java.io.UnsupportedEncodingException; + +/** + * Tests cases for {@link ByteString#isValidUtf8()}. This includes three + * brute force tests that actually test every permutation of one byte, two byte, + * and three byte sequences to ensure that the method produces the right result + * for every possible byte encoding where "right" means it's consistent with + * java's UTF-8 string encoding/decoding such that the method returns true for + * any sequence that will round trip when converted to a String and then back to + * bytes and will return false for any sequence that will not round trip. + * See also {@link IsValidUtf8FourByteTest}. It also includes some + * other more targeted tests. + * + * @author jonp@google.com (Jon Perlow) + * @author martinrb@google.com (Martin Buchholz) + */ +public class IsValidUtf8Test extends TestCase { + + /** + * Tests that round tripping of all two byte permutations work. + */ + public void testIsValidUtf8_1Byte() throws UnsupportedEncodingException { + IsValidUtf8TestUtil.testBytes(1, + IsValidUtf8TestUtil.EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT); + } + + /** + * Tests that round tripping of all two byte permutations work. + */ + public void testIsValidUtf8_2Bytes() throws UnsupportedEncodingException { + IsValidUtf8TestUtil.testBytes(2, + IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT); + } + + /** + * Tests that round tripping of all three byte permutations work. + */ + public void testIsValidUtf8_3Bytes() throws UnsupportedEncodingException { + IsValidUtf8TestUtil.testBytes(3, + IsValidUtf8TestUtil.EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT); + } + + /** + * Tests that round tripping of a sample of four byte permutations work. + * All permutations are prohibitively expensive to test for automated runs; + * {@link IsValidUtf8FourByteTest} is used for full coverage. This method + * tests specific four-byte cases. + */ + public void testIsValidUtf8_4BytesSamples() + throws UnsupportedEncodingException { + // Valid 4 byte. + assertValidUtf8(0xF0, 0xA4, 0xAD, 0xA2); + + // Bad trailing bytes + assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0x7F); + assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0xC0); + + // Special cases for byte2 + assertInvalidUtf8(0xF0, 0x8F, 0xAD, 0xA2); + assertInvalidUtf8(0xF4, 0x90, 0xAD, 0xA2); + } + + /** + * Tests some hard-coded test cases. + */ + public void testSomeSequences() { + // Empty + assertTrue(asBytes("").isValidUtf8()); + + // One-byte characters, including control characters + assertTrue(asBytes("\u0000abc\u007f").isValidUtf8()); + + // Two-byte characters + assertTrue(asBytes("\u00a2\u00a2").isValidUtf8()); + + // Three-byte characters + assertTrue(asBytes("\u020ac\u020ac").isValidUtf8()); + + // Four-byte characters + assertTrue(asBytes("\u024B62\u024B62").isValidUtf8()); + + // Mixed string + assertTrue( + asBytes("a\u020ac\u00a2b\\u024B62u020acc\u00a2de\u024B62") + .isValidUtf8()); + + // Not a valid string + assertInvalidUtf8(-1, 0, -1, 0); + } + + private byte[] toByteArray(int... bytes) { + byte[] realBytes = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) { + realBytes[i] = (byte) bytes[i]; + } + return realBytes; + } + + private ByteString toByteString(int... bytes) { + return ByteString.copyFrom(toByteArray(bytes)); + } + + private void assertValidUtf8(int[] bytes, boolean not) { + byte[] realBytes = toByteArray(bytes); + assertTrue(not ^ Utf8.isValidUtf8(realBytes)); + assertTrue(not ^ Utf8.isValidUtf8(realBytes, 0, bytes.length)); + ByteString lit = ByteString.copyFrom(realBytes); + ByteString sub = lit.substring(0, bytes.length); + assertTrue(not ^ lit.isValidUtf8()); + assertTrue(not ^ sub.isValidUtf8()); + ByteString[] ropes = { + RopeByteString.newInstanceForTest(ByteString.EMPTY, lit), + RopeByteString.newInstanceForTest(ByteString.EMPTY, sub), + RopeByteString.newInstanceForTest(lit, ByteString.EMPTY), + RopeByteString.newInstanceForTest(sub, ByteString.EMPTY), + RopeByteString.newInstanceForTest(sub, lit) + }; + for (ByteString rope : ropes) { + assertTrue(not ^ rope.isValidUtf8()); + } + } + + private void assertValidUtf8(int... bytes) { + assertValidUtf8(bytes, false); + } + + private void assertInvalidUtf8(int... bytes) { + assertValidUtf8(bytes, true); + } + + private static ByteString asBytes(String s) { + return ByteString.copyFromUtf8(s); + } + + public void testShardsHaveExpectedRoundTrippables() { + // A sanity check. + int actual = 0; + for (Shard shard : IsValidUtf8TestUtil.FOUR_BYTE_SHARDS) { + actual += shard.expected; + } + assertEquals(IsValidUtf8TestUtil.EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT, + actual); + } +} diff --git a/java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java b/java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java new file mode 100644 index 0000000..4cb3d5b --- /dev/null +++ b/java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java @@ -0,0 +1,421 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import static junit.framework.Assert.*; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.logging.Logger; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.Charset; +import java.nio.charset.CodingErrorAction; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CoderResult; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; + +/** + * Shared testing code for {@link IsValidUtf8Test} and + * {@link IsValidUtf8FourByteTest}. + * + * @author jonp@google.com (Jon Perlow) + * @author martinrb@google.com (Martin Buchholz) + */ +class IsValidUtf8TestUtil { + private static Logger logger = Logger.getLogger( + IsValidUtf8TestUtil.class.getName()); + + // 128 - [chars 0x0000 to 0x007f] + static long ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x007f - 0x0000 + 1; + + // 128 + static long EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT = + ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS; + + // 1920 [chars 0x0080 to 0x07FF] + static long TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x07FF - 0x0080 + 1; + + // 18,304 + static long EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT = + // Both bytes are one byte characters + (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 2) + + // The possible number of two byte characters + TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS; + + // 2048 + static long THREE_BYTE_SURROGATES = 2 * 1024; + + // 61,440 [chars 0x0800 to 0xFFFF, minus surrogates] + static long THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS = + 0xFFFF - 0x0800 + 1 - THREE_BYTE_SURROGATES; + + // 2,650,112 + static long EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT = + // All one byte characters + (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 3) + + // One two byte character and a one byte character + 2 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * + ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS + + // Three byte characters + THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS; + + // 1,048,576 [chars 0x10000L to 0x10FFFF] + static long FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x10FFFF - 0x10000L + 1; + + // 289,571,839 + static long EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT = + // All one byte characters + (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 4) + + // One and three byte characters + 2 * THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS * + ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS + + // Two two byte characters + TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS + + // Permutations of one and two byte characters + 3 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * + ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS * + ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS + + // Four byte characters + FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS; + + static class Shard { + final long index; + final long start; + final long lim; + final long expected; + + + public Shard(long index, long start, long lim, long expected) { + assertTrue(start < lim); + this.index = index; + this.start = start; + this.lim = lim; + this.expected = expected; + } + } + + static final long[] FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES = + generateFourByteShardsExpectedRunnables(); + + private static long[] generateFourByteShardsExpectedRunnables() { + long[] expected = new long[128]; + + // 0-63 are all 5300224 + for (int i = 0; i <= 63; i++) { + expected[i] = 5300224; + } + + // 97-111 are all 2342912 + for (int i = 97; i <= 111; i++) { + expected[i] = 2342912; + } + + // 113-117 are all 1048576 + for (int i = 113; i <= 117; i++) { + expected[i] = 1048576; + } + + // One offs + expected[112] = 786432; + expected[118] = 786432; + expected[119] = 1048576; + expected[120] = 458752; + expected[121] = 524288; + expected[122] = 65536; + + // Anything not assigned was the default 0. + return expected; + } + + static final List FOUR_BYTE_SHARDS = generateFourByteShards( + 128, FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES); + + + private static List generateFourByteShards( + int numShards, long[] expected) { + assertEquals(numShards, expected.length); + List shards = new ArrayList(numShards); + long LIM = 1L << 32; + long increment = LIM / numShards; + assertTrue(LIM % numShards == 0); + for (int i = 0; i < numShards; i++) { + shards.add(new Shard(i, + increment * i, + increment * (i + 1), + expected[i])); + } + return shards; + } + + /** + * Helper to run the loop to test all the permutations for the number of bytes + * specified. + * + * @param numBytes the number of bytes in the byte array + * @param expectedCount the expected number of roundtrippable permutations + */ + static void testBytes(int numBytes, long expectedCount) + throws UnsupportedEncodingException { + testBytes(numBytes, expectedCount, 0, -1); + } + + /** + * Helper to run the loop to test all the permutations for the number of bytes + * specified. This overload is useful for debugging to get the loop to start + * at a certain character. + * + * @param numBytes the number of bytes in the byte array + * @param expectedCount the expected number of roundtrippable permutations + * @param start the starting bytes encoded as a long as big-endian + * @param lim the limit of bytes to process encoded as a long as big-endian, + * or -1 to mean the max limit for numBytes + */ + static void testBytes(int numBytes, long expectedCount, long start, long lim) + throws UnsupportedEncodingException { + Random rnd = new Random(); + byte[] bytes = new byte[numBytes]; + + if (lim == -1) { + lim = 1L << (numBytes * 8); + } + long count = 0; + long countRoundTripped = 0; + for (long byteChar = start; byteChar < lim; byteChar++) { + long tmpByteChar = byteChar; + for (int i = 0; i < numBytes; i++) { + bytes[bytes.length - i - 1] = (byte) tmpByteChar; + tmpByteChar = tmpByteChar >> 8; + } + ByteString bs = ByteString.copyFrom(bytes); + boolean isRoundTrippable = bs.isValidUtf8(); + String s = new String(bytes, "UTF-8"); + byte[] bytesReencoded = s.getBytes("UTF-8"); + boolean bytesEqual = Arrays.equals(bytes, bytesReencoded); + + if (bytesEqual != isRoundTrippable) { + outputFailure(byteChar, bytes, bytesReencoded); + } + + // Check agreement with static Utf8 methods. + assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes)); + assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes, 0, numBytes)); + + // Test partial sequences. + // Partition numBytes into three segments (not necessarily non-empty). + int i = rnd.nextInt(numBytes); + int j = rnd.nextInt(numBytes); + if (j < i) { + int tmp = i; i = j; j = tmp; + } + int state1 = Utf8.partialIsValidUtf8(Utf8.COMPLETE, bytes, 0, i); + int state2 = Utf8.partialIsValidUtf8(state1, bytes, i, j); + int state3 = Utf8.partialIsValidUtf8(state2, bytes, j, numBytes); + if (isRoundTrippable != (state3 == Utf8.COMPLETE)) { + System.out.printf("state=%04x %04x %04x i=%d j=%d%n", + state1, state2, state3, i, j); + outputFailure(byteChar, bytes, bytesReencoded); + } + assertEquals(isRoundTrippable, (state3 == Utf8.COMPLETE)); + + // Test ropes built out of small partial sequences + ByteString rope = RopeByteString.newInstanceForTest( + bs.substring(0, i), + RopeByteString.newInstanceForTest( + bs.substring(i, j), + bs.substring(j, numBytes))); + assertSame(RopeByteString.class, rope.getClass()); + + ByteString[] byteStrings = { bs, bs.substring(0, numBytes), rope }; + for (ByteString x : byteStrings) { + assertEquals(isRoundTrippable, + x.isValidUtf8()); + assertEquals(state3, + x.partialIsValidUtf8(Utf8.COMPLETE, 0, numBytes)); + + assertEquals(state1, + x.partialIsValidUtf8(Utf8.COMPLETE, 0, i)); + assertEquals(state1, + x.substring(0, i).partialIsValidUtf8(Utf8.COMPLETE, 0, i)); + assertEquals(state2, + x.partialIsValidUtf8(state1, i, j - i)); + assertEquals(state2, + x.substring(i, j).partialIsValidUtf8(state1, 0, j - i)); + assertEquals(state3, + x.partialIsValidUtf8(state2, j, numBytes - j)); + assertEquals(state3, + x.substring(j, numBytes) + .partialIsValidUtf8(state2, 0, numBytes - j)); + } + + // ByteString reduplication should not affect its UTF-8 validity. + ByteString ropeADope = + RopeByteString.newInstanceForTest(bs, bs.substring(0, numBytes)); + assertEquals(isRoundTrippable, ropeADope.isValidUtf8()); + + if (isRoundTrippable) { + countRoundTripped++; + } + count++; + if (byteChar != 0 && byteChar % 1000000L == 0) { + logger.info("Processed " + (byteChar / 1000000L) + + " million characters"); + } + } + logger.info("Round tripped " + countRoundTripped + " of " + count); + assertEquals(expectedCount, countRoundTripped); + } + + /** + * Variation of {@link #testBytes} that does less allocation using the + * low-level encoders/decoders directly. Checked in because it's useful for + * debugging when trying to process bytes faster, but since it doesn't use the + * actual String class, it's possible for incompatibilities to develop + * (although unlikely). + * + * @param numBytes the number of bytes in the byte array + * @param expectedCount the expected number of roundtrippable permutations + * @param start the starting bytes encoded as a long as big-endian + * @param lim the limit of bytes to process encoded as a long as big-endian, + * or -1 to mean the max limit for numBytes + */ + void testBytesUsingByteBuffers( + int numBytes, long expectedCount, long start, long lim) + throws UnsupportedEncodingException { + CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + byte[] bytes = new byte[numBytes]; + int maxChars = (int) (decoder.maxCharsPerByte() * numBytes) + 1; + char[] charsDecoded = + new char[(int) (decoder.maxCharsPerByte() * numBytes) + 1]; + int maxBytes = (int) (encoder.maxBytesPerChar() * maxChars) + 1; + byte[] bytesReencoded = new byte[maxBytes]; + + ByteBuffer bb = ByteBuffer.wrap(bytes); + CharBuffer cb = CharBuffer.wrap(charsDecoded); + ByteBuffer bbReencoded = ByteBuffer.wrap(bytesReencoded); + if (lim == -1) { + lim = 1L << (numBytes * 8); + } + long count = 0; + long countRoundTripped = 0; + for (long byteChar = start; byteChar < lim; byteChar++) { + bb.rewind(); + bb.limit(bytes.length); + cb.rewind(); + cb.limit(charsDecoded.length); + bbReencoded.rewind(); + bbReencoded.limit(bytesReencoded.length); + encoder.reset(); + decoder.reset(); + long tmpByteChar = byteChar; + for (int i = 0; i < bytes.length; i++) { + bytes[bytes.length - i - 1] = (byte) tmpByteChar; + tmpByteChar = tmpByteChar >> 8; + } + boolean isRoundTrippable = ByteString.copyFrom(bytes).isValidUtf8(); + CoderResult result = decoder.decode(bb, cb, true); + assertFalse(result.isError()); + result = decoder.flush(cb); + assertFalse(result.isError()); + + int charLen = cb.position(); + cb.rewind(); + cb.limit(charLen); + result = encoder.encode(cb, bbReencoded, true); + assertFalse(result.isError()); + result = encoder.flush(bbReencoded); + assertFalse(result.isError()); + + boolean bytesEqual = true; + int bytesLen = bbReencoded.position(); + if (bytesLen != numBytes) { + bytesEqual = false; + } else { + for (int i = 0; i < numBytes; i++) { + if (bytes[i] != bytesReencoded[i]) { + bytesEqual = false; + break; + } + } + } + if (bytesEqual != isRoundTrippable) { + outputFailure(byteChar, bytes, bytesReencoded, bytesLen); + } + + count++; + if (isRoundTrippable) { + countRoundTripped++; + } + if (byteChar != 0 && byteChar % 1000000 == 0) { + logger.info("Processed " + (byteChar / 1000000) + + " million characters"); + } + } + logger.info("Round tripped " + countRoundTripped + " of " + count); + assertEquals(expectedCount, countRoundTripped); + } + + private static void outputFailure(long byteChar, byte[] bytes, byte[] after) { + outputFailure(byteChar, bytes, after, after.length); + } + + private static void outputFailure(long byteChar, byte[] bytes, byte[] after, + int len) { + fail("Failure: (" + Long.toHexString(byteChar) + ") " + + toHexString(bytes) + " => " + toHexString(after, len)); + } + + private static String toHexString(byte[] b) { + return toHexString(b, b.length); + } + + private static String toHexString(byte[] b, int len) { + StringBuilder s = new StringBuilder(); + s.append("\""); + for (int i = 0; i < len; i++) { + if (i > 0) { + s.append(" "); + } + s.append(String.format("%02x", b[i] & 0xFF)); + } + s.append("\""); + return s.toString(); + } + +} diff --git a/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java b/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java new file mode 100644 index 0000000..33a7297 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java @@ -0,0 +1,134 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import protobuf_unittest.UnittestProto.TestAllExtensions; +import protobuf_unittest.UnittestProto.TestAllTypes; + +import java.io.IOException; +import junit.framework.TestCase; + +/** + * Unit test for {@link LazyFieldLite}. + * + * @author xiangl@google.com (Xiang Li) + */ +public class LazyFieldLiteTest extends TestCase { + + public void testGetValue() { + MessageLite message = TestUtil.getAllSet(); + LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message); + assertEquals(message, lazyField.getValue(TestAllTypes.getDefaultInstance())); + changeValue(lazyField); + assertNotEqual(message, lazyField.getValue(TestAllTypes.getDefaultInstance())); + } + + public void testGetValueEx() throws Exception { + TestAllExtensions message = TestUtil.getAllExtensionsSet(); + LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message); + assertEquals(message, lazyField.getValue(TestAllExtensions.getDefaultInstance())); + changeValue(lazyField); + assertNotEqual(message, lazyField.getValue(TestAllExtensions.getDefaultInstance())); + } + + public void testSetValue() { + MessageLite message = TestUtil.getAllSet(); + LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message); + changeValue(lazyField); + assertNotEqual(message, lazyField.getValue(TestAllTypes.getDefaultInstance())); + message = lazyField.getValue(TestAllTypes.getDefaultInstance()); + changeValue(lazyField); + assertEquals(message, lazyField.getValue(TestAllTypes.getDefaultInstance())); + } + + public void testSetValueEx() throws Exception { + TestAllExtensions message = TestUtil.getAllExtensionsSet(); + LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message); + changeValue(lazyField); + assertNotEqual(message, lazyField.getValue(TestAllExtensions.getDefaultInstance())); + MessageLite value = lazyField.getValue(TestAllExtensions.getDefaultInstance()); + changeValue(lazyField); + assertEquals(value, lazyField.getValue(TestAllExtensions.getDefaultInstance())); + } + + public void testGetSerializedSize() { + MessageLite message = TestUtil.getAllSet(); + LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message); + assertEquals(message.getSerializedSize(), lazyField.getSerializedSize()); + changeValue(lazyField); + assertNotEqual(message.getSerializedSize(), lazyField.getSerializedSize()); + } + + public void testGetSerializedSizeEx() throws Exception { + TestAllExtensions message = TestUtil.getAllExtensionsSet(); + LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message); + assertEquals(message.getSerializedSize(), lazyField.getSerializedSize()); + changeValue(lazyField); + assertNotEqual(message.getSerializedSize(), lazyField.getSerializedSize()); + } + + public void testGetByteString() { + MessageLite message = TestUtil.getAllSet(); + LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message); + assertEquals(message.toByteString(), lazyField.toByteString()); + changeValue(lazyField); + assertNotEqual(message.toByteString(), lazyField.toByteString()); + } + + public void testGetByteStringEx() throws Exception { + TestAllExtensions message = TestUtil.getAllExtensionsSet(); + LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message); + assertEquals(message.toByteString(), lazyField.toByteString()); + changeValue(lazyField); + assertNotEqual(message.toByteString(), lazyField.toByteString()); + } + + + // Help methods. + + private LazyFieldLite createLazyFieldLiteFromMessage(MessageLite message) { + ByteString bytes = message.toByteString(); + return new LazyFieldLite(TestUtil.getExtensionRegistry(), bytes); + } + + private void changeValue(LazyFieldLite lazyField) { + TestAllTypes.Builder builder = TestUtil.getAllSet().toBuilder(); + builder.addRepeatedBool(true); + MessageLite newMessage = builder.build(); + lazyField.setValue(newMessage); + } + + private void assertNotEqual(Object unexpected, Object actual) { + assertFalse(unexpected == actual + || (unexpected != null && unexpected.equals(actual))); + } + +} diff --git a/java/src/test/java/com/google/protobuf/LazyFieldTest.java b/java/src/test/java/com/google/protobuf/LazyFieldTest.java new file mode 100644 index 0000000..5aedc32 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/LazyFieldTest.java @@ -0,0 +1,121 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import protobuf_unittest.UnittestProto.TestAllExtensions; +import protobuf_unittest.UnittestProto.TestAllTypes; + +import java.io.IOException; +import junit.framework.TestCase; + +/** + * Unit test for {@link LazyField}. + * + * @author xiangl@google.com (Xiang Li) + */ +public class LazyFieldTest extends TestCase { + public void testHashCode() { + MessageLite message = TestUtil.getAllSet(); + LazyField lazyField = + createLazyFieldFromMessage(message); + assertEquals(message.hashCode(), lazyField.hashCode()); + lazyField.getValue(); + assertEquals(message.hashCode(), lazyField.hashCode()); + changeValue(lazyField); + // make sure two messages have different hash code + assertNotEqual(message.hashCode(), lazyField.hashCode()); + } + + public void testHashCodeEx() throws Exception { + TestAllExtensions message = TestUtil.getAllExtensionsSet(); + LazyField lazyField = createLazyFieldFromMessage(message); + assertEquals(message.hashCode(), lazyField.hashCode()); + lazyField.getValue(); + assertEquals(message.hashCode(), lazyField.hashCode()); + changeValue(lazyField); + // make sure two messages have different hash code + assertNotEqual(message.hashCode(), lazyField.hashCode()); + } + + public void testGetValue() { + MessageLite message = TestUtil.getAllSet(); + LazyField lazyField = createLazyFieldFromMessage(message); + assertEquals(message, lazyField.getValue()); + changeValue(lazyField); + assertNotEqual(message, lazyField.getValue()); + } + + public void testGetValueEx() throws Exception { + TestAllExtensions message = TestUtil.getAllExtensionsSet(); + LazyField lazyField = createLazyFieldFromMessage(message); + assertEquals(message, lazyField.getValue()); + changeValue(lazyField); + assertNotEqual(message, lazyField.getValue()); + } + + public void testEqualsObject() { + MessageLite message = TestUtil.getAllSet(); + LazyField lazyField = createLazyFieldFromMessage(message); + assertTrue(lazyField.equals(message)); + changeValue(lazyField); + assertFalse(lazyField.equals(message)); + assertFalse(message.equals(lazyField.getValue())); + } + + public void testEqualsObjectEx() throws Exception { + TestAllExtensions message = TestUtil.getAllExtensionsSet(); + LazyField lazyField = createLazyFieldFromMessage(message); + assertTrue(lazyField.equals(message)); + changeValue(lazyField); + assertFalse(lazyField.equals(message)); + assertFalse(message.equals(lazyField.getValue())); + } + + // Help methods. + + private LazyField createLazyFieldFromMessage(MessageLite message) { + ByteString bytes = message.toByteString(); + return new LazyField(message.getDefaultInstanceForType(), + TestUtil.getExtensionRegistry(), bytes); + } + + private void changeValue(LazyField lazyField) { + TestAllTypes.Builder builder = TestUtil.getAllSet().toBuilder(); + builder.addRepeatedBool(true); + MessageLite newMessage = builder.build(); + lazyField.setValue(newMessage); + } + + private void assertNotEqual(Object unexpected, Object actual) { + assertFalse(unexpected == actual + || (unexpected != null && unexpected.equals(actual))); + } +} diff --git a/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java b/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java new file mode 100644 index 0000000..63028db --- /dev/null +++ b/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java @@ -0,0 +1,319 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import protobuf_unittest.LazyFieldsLite.LazyInnerMessageLite; +import protobuf_unittest.LazyFieldsLite.LazyMessageLite; +import protobuf_unittest.LazyFieldsLite.LazyNestedInnerMessageLite; + +import junit.framework.TestCase; + +import org.easymock.classextension.EasyMock; + +import java.util.ArrayList; + +/** + * Unit test for messages with lazy fields. + * + * @author niwasaki@google.com (Naoki Iwasaki) + */ +public class LazyMessageLiteTest extends TestCase { + + private Parser originalLazyInnerMessageLiteParser; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + originalLazyInnerMessageLiteParser = LazyInnerMessageLite.PARSER; + } + + @Override + protected void tearDown() throws Exception { + LazyInnerMessageLite.PARSER = originalLazyInnerMessageLiteParser; + + super.tearDown(); + } + + public void testSetValues() { + LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder() + .setNum(3) + .build(); + LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder() + .setNum(2) + .setNested(nested) + .build(); + LazyMessageLite outer = LazyMessageLite.newBuilder() + .setNum(1) + .setInner(inner) + .setOneofNum(123) + .setOneofInner(inner) + .build(); + + assertEquals(1, outer.getNum()); + assertEquals(421, outer.getNumWithDefault()); + + assertEquals(2, outer.getInner().getNum()); + assertEquals(42, outer.getInner().getNumWithDefault()); + + assertEquals(3, outer.getInner().getNested().getNum()); + assertEquals(4, outer.getInner().getNested().getNumWithDefault()); + + assertFalse(outer.hasOneofNum()); + assertTrue(outer.hasOneofInner()); + + assertEquals(2, outer.getOneofInner().getNum()); + assertEquals(42, outer.getOneofInner().getNumWithDefault()); + assertEquals(3, outer.getOneofInner().getNested().getNum()); + assertEquals(4, outer.getOneofInner().getNested().getNumWithDefault()); + } + + public void testSetRepeatedValues() { + LazyMessageLite outer = LazyMessageLite.newBuilder() + .setNum(1) + .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119)) + .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122)) + .build(); + + assertEquals(1, outer.getNum()); + assertEquals(2, outer.getRepeatedInnerCount()); + assertEquals(119, outer.getRepeatedInner(0).getNum()); + assertEquals(122, outer.getRepeatedInner(1).getNum()); + } + + public void testAddAll() { + ArrayList inners = new ArrayList(); + int count = 4; + for (int i = 0; i < count; i++) { + LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder() + .setNum(i) + .build(); + inners.add(inner); + } + + LazyMessageLite outer = LazyMessageLite.newBuilder() + .addAllRepeatedInner(inners) + .build(); + assertEquals(count, outer.getRepeatedInnerCount()); + for (int i = 0; i < count; i++) { + assertEquals(i, outer.getRepeatedInner(i).getNum()); + } + } + + public void testGetDefaultValues() { + LazyMessageLite outer = LazyMessageLite.newBuilder() + .build(); + + assertEquals(0, outer.getNum()); + assertEquals(421, outer.getNumWithDefault()); + + assertEquals(0, outer.getInner().getNum()); + assertEquals(42, outer.getInner().getNumWithDefault()); + + assertEquals(0, outer.getInner().getNested().getNum()); + assertEquals(4, outer.getInner().getNested().getNumWithDefault()); + + assertEquals(0, outer.getOneofNum()); + + assertEquals(0, outer.getOneofInner().getNum()); + assertEquals(42, outer.getOneofInner().getNumWithDefault()); + assertEquals(0, outer.getOneofInner().getNested().getNum()); + assertEquals(4, outer.getOneofInner().getNested().getNumWithDefault()); + } + + public void testClearValues() { + LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder() + .setNum(115) + .build(); + + LazyMessageLite.Builder outerBuilder = LazyMessageLite.newBuilder(); + + assertEquals(0, outerBuilder.build().getNum()); + + + // Set/Clear num + outerBuilder.setNum(100); + + assertEquals(100, outerBuilder.build().getNum()); + assertEquals(421, outerBuilder.build().getNumWithDefault()); + assertFalse(outerBuilder.build().hasInner()); + + outerBuilder.clearNum(); + + assertEquals(0, outerBuilder.build().getNum()); + assertEquals(421, outerBuilder.build().getNumWithDefault()); + assertFalse(outerBuilder.build().hasInner()); + + + // Set/Clear all + outerBuilder.setNum(100) + .setInner(inner) + .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119)) + .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122)) + .setOneofInner(LazyInnerMessageLite.newBuilder().setNum(123)); + + LazyMessageLite outer = outerBuilder.build(); + assertEquals(100, outer.getNum()); + assertEquals(421, outer.getNumWithDefault()); + assertTrue(outer.hasInner()); + assertEquals(115, outer.getInner().getNum()); + assertEquals(2, outer.getRepeatedInnerCount()); + assertEquals(119, outer.getRepeatedInner(0).getNum()); + assertEquals(122, outer.getRepeatedInner(1).getNum()); + assertTrue(outer.hasOneofInner()); + assertEquals(123, outer.getOneofInner().getNum()); + + outerBuilder.clear(); + + outer = outerBuilder.build(); + + assertEquals(0, outer.getNum()); + assertEquals(421, outer.getNumWithDefault()); + assertFalse(outer.hasInner()); + assertEquals(0, outer.getRepeatedInnerCount()); + assertFalse(outer.hasOneofInner()); + assertEquals(0, outer.getOneofInner().getNum()); + } + + public void testMergeValues() { + LazyMessageLite outerBase = LazyMessageLite.newBuilder() + .setNumWithDefault(122) + .build(); + + LazyInnerMessageLite innerMerging = LazyInnerMessageLite.newBuilder() + .setNum(115) + .build(); + LazyMessageLite outerMerging = LazyMessageLite.newBuilder() + .setNum(119) + .setInner(innerMerging) + .setOneofInner(innerMerging) + .build(); + + LazyMessageLite merged = LazyMessageLite + .newBuilder(outerBase) + .mergeFrom(outerMerging) + .build(); + assertEquals(119, merged.getNum()); + assertEquals(122, merged.getNumWithDefault()); + assertEquals(115, merged.getInner().getNum()); + assertEquals(42, merged.getInner().getNumWithDefault()); + assertEquals(115, merged.getOneofInner().getNum()); + assertEquals(42, merged.getOneofInner().getNumWithDefault()); + } + + public void testMergeDefaultValues() { + LazyInnerMessageLite innerBase = LazyInnerMessageLite.newBuilder() + .setNum(115) + .build(); + LazyMessageLite outerBase = LazyMessageLite.newBuilder() + .setNum(119) + .setNumWithDefault(122) + .setInner(innerBase) + .setOneofInner(innerBase) + .build(); + + LazyMessageLite outerMerging = LazyMessageLite.newBuilder() + .build(); + + LazyMessageLite merged = LazyMessageLite + .newBuilder(outerBase) + .mergeFrom(outerMerging) + .build(); + // Merging default-instance shouldn't overwrite values in the base message. + assertEquals(119, merged.getNum()); + assertEquals(122, merged.getNumWithDefault()); + assertEquals(115, merged.getInner().getNum()); + assertEquals(42, merged.getInner().getNumWithDefault()); + assertEquals(115, merged.getOneofInner().getNum()); + assertEquals(42, merged.getOneofInner().getNumWithDefault()); + } + + public void testSerialize() throws InvalidProtocolBufferException { + LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder() + .setNum(3) + .build(); + LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder() + .setNum(2) + .setNested(nested) + .build(); + LazyMessageLite outer = LazyMessageLite.newBuilder() + .setNum(1) + .setInner(inner) + .setOneofInner(inner) + .build(); + + ByteString bytes = outer.toByteString(); + assertEquals(bytes.size(), outer.getSerializedSize()); + + LazyMessageLite deserialized = LazyMessageLite.parseFrom(bytes); + + assertEquals(1, deserialized.getNum()); + assertEquals(421, deserialized.getNumWithDefault()); + + assertEquals(2, deserialized.getInner().getNum()); + assertEquals(42, deserialized.getInner().getNumWithDefault()); + + assertEquals(3, deserialized.getInner().getNested().getNum()); + assertEquals(4, deserialized.getInner().getNested().getNumWithDefault()); + + assertEquals(2, deserialized.getOneofInner().getNum()); + assertEquals(42, deserialized.getOneofInner().getNumWithDefault()); + assertEquals(3, deserialized.getOneofInner().getNested().getNum()); + assertEquals(4, deserialized.getOneofInner().getNested().getNumWithDefault()); + + assertEquals(bytes, deserialized.toByteString()); + } + + public void testLaziness() throws InvalidProtocolBufferException { + LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder() + .setNum(2) + .build(); + LazyMessageLite outer = LazyMessageLite.newBuilder() + .setNum(1) + .setInner(inner) + .setOneofInner(inner) + .build(); + ByteString bytes = outer.toByteString(); + + + // The parser for inner / oneofInner message shouldn't be used if + // getInner / getOneofInner is not called. + LazyInnerMessageLite.PARSER = EasyMock.createStrictMock(Parser.class); + + EasyMock.replay(LazyInnerMessageLite.PARSER); + + LazyMessageLite deserialized = LazyMessageLite.parseFrom(bytes); + assertEquals(1, deserialized.getNum()); + assertEquals(421, deserialized.getNumWithDefault()); + + EasyMock.verify(LazyInnerMessageLite.PARSER); + } +} diff --git a/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java b/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java new file mode 100644 index 0000000..850658c --- /dev/null +++ b/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java @@ -0,0 +1,174 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.List; + +/** + * Tests for {@link LazyStringArrayList}. + * + * @author jonp@google.com (Jon Perlow) + */ +public class LazyStringArrayListTest extends TestCase { + + private static String STRING_A = "A"; + private static String STRING_B = "B"; + private static String STRING_C = "C"; + + private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A"); + private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B"); + private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C"); + + public void testJustStrings() { + LazyStringArrayList list = new LazyStringArrayList(); + list.add(STRING_A); + list.add(STRING_B); + list.add(STRING_C); + + assertEquals(3, list.size()); + assertSame(STRING_A, list.get(0)); + assertSame(STRING_B, list.get(1)); + assertSame(STRING_C, list.get(2)); + + list.set(1, STRING_C); + assertSame(STRING_C, list.get(1)); + + list.remove(1); + assertSame(STRING_A, list.get(0)); + assertSame(STRING_C, list.get(1)); + + List byteStringList = list.asByteStringList(); + assertEquals(BYTE_STRING_A, byteStringList.get(0)); + assertEquals(BYTE_STRING_C, byteStringList.get(1)); + + // Underlying list should be transformed. + assertSame(byteStringList.get(0), list.getByteString(0)); + assertSame(byteStringList.get(1), list.getByteString(1)); + } + + public void testJustByteString() { + LazyStringArrayList list = new LazyStringArrayList(); + list.add(BYTE_STRING_A); + list.add(BYTE_STRING_B); + list.add(BYTE_STRING_C); + + assertEquals(3, list.size()); + assertSame(BYTE_STRING_A, list.getByteString(0)); + assertSame(BYTE_STRING_B, list.getByteString(1)); + assertSame(BYTE_STRING_C, list.getByteString(2)); + + list.remove(1); + assertSame(BYTE_STRING_A, list.getByteString(0)); + assertSame(BYTE_STRING_C, list.getByteString(1)); + + List byteStringList = list.asByteStringList(); + assertSame(BYTE_STRING_A, byteStringList.get(0)); + assertSame(BYTE_STRING_C, byteStringList.get(1)); + } + + public void testConversionBackAndForth() { + LazyStringArrayList list = new LazyStringArrayList(); + list.add(STRING_A); + list.add(BYTE_STRING_B); + list.add(BYTE_STRING_C); + + // String a should be the same because it was originally a string + assertSame(STRING_A, list.get(0)); + + // String b and c should be different because the string has to be computed + // from the ByteString + String bPrime = list.get(1); + assertNotSame(STRING_B, bPrime); + assertEquals(STRING_B, bPrime); + String cPrime = list.get(2); + assertNotSame(STRING_C, cPrime); + assertEquals(STRING_C, cPrime); + + // String c and c should stay the same once cached. + assertSame(bPrime, list.get(1)); + assertSame(cPrime, list.get(2)); + + // ByteString needs to be computed from string for both a and b + ByteString aPrimeByteString = list.getByteString(0); + assertEquals(BYTE_STRING_A, aPrimeByteString); + ByteString bPrimeByteString = list.getByteString(1); + assertNotSame(BYTE_STRING_B, bPrimeByteString); + assertEquals(BYTE_STRING_B, list.getByteString(1)); + + // Once cached, ByteString should stay cached. + assertSame(aPrimeByteString, list.getByteString(0)); + assertSame(bPrimeByteString, list.getByteString(1)); + } + + public void testCopyConstructorCopiesByReference() { + LazyStringArrayList list1 = new LazyStringArrayList(); + list1.add(STRING_A); + list1.add(BYTE_STRING_B); + list1.add(BYTE_STRING_C); + + LazyStringArrayList list2 = new LazyStringArrayList(list1); + assertEquals(3, list2.size()); + assertSame(STRING_A, list2.get(0)); + assertSame(BYTE_STRING_B, list2.getByteString(1)); + assertSame(BYTE_STRING_C, list2.getByteString(2)); + } + + public void testListCopyConstructor() { + List list1 = new ArrayList(); + list1.add(STRING_A); + list1.add(STRING_B); + list1.add(STRING_C); + + LazyStringArrayList list2 = new LazyStringArrayList(list1); + assertEquals(3, list2.size()); + assertSame(STRING_A, list2.get(0)); + assertSame(STRING_B, list2.get(1)); + assertSame(STRING_C, list2.get(2)); + } + + public void testAddAllCopiesByReferenceIfPossible() { + LazyStringArrayList list1 = new LazyStringArrayList(); + list1.add(STRING_A); + list1.add(BYTE_STRING_B); + list1.add(BYTE_STRING_C); + + LazyStringArrayList list2 = new LazyStringArrayList(); + list2.addAll(list1); + + assertEquals(3, list2.size()); + assertSame(STRING_A, list2.get(0)); + assertSame(BYTE_STRING_B, list2.getByteString(1)); + assertSame(BYTE_STRING_C, list2.getByteString(2)); + } +} diff --git a/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java b/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java new file mode 100644 index 0000000..fe9599e --- /dev/null +++ b/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java @@ -0,0 +1,143 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + + +import protobuf_unittest.UnittestProto; + +import junit.framework.TestCase; + +import java.io.IOException; + +/** + * Tests to make sure the lazy conversion of UTF8-encoded byte arrays to + * strings works correctly. + * + * @author jonp@google.com (Jon Perlow) + */ +public class LazyStringEndToEndTest extends TestCase { + + private static ByteString TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8 = + ByteString.copyFrom(new byte[] { + 114, 4, -1, 0, -1, 0, -30, 2, 4, -1, + 0, -1, 0, -30, 2, 4, -1, 0, -1, 0, }); + + private ByteString encodedTestAllTypes; + + @Override + protected void setUp() throws Exception { + super.setUp(); + this.encodedTestAllTypes = UnittestProto.TestAllTypes.newBuilder() + .setOptionalString("foo") + .addRepeatedString("bar") + .addRepeatedString("baz") + .build() + .toByteString(); + } + + /** + * Tests that an invalid UTF8 string will roundtrip through a parse + * and serialization. + */ + public void testParseAndSerialize() throws InvalidProtocolBufferException { + UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom( + TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8); + ByteString bytes = tV2.toByteString(); + assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes); + + tV2.getOptionalString(); + bytes = tV2.toByteString(); + assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes); + } + + public void testParseAndWrite() throws IOException { + UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom( + TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8); + byte[] sink = new byte[TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8.size()]; + CodedOutputStream outputStream = CodedOutputStream.newInstance(sink); + tV2.writeTo(outputStream); + outputStream.flush(); + assertEquals( + TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, + ByteString.copyFrom(sink)); + } + + public void testCaching() { + String a = "a"; + String b = "b"; + String c = "c"; + UnittestProto.TestAllTypes proto = UnittestProto.TestAllTypes.newBuilder() + .setOptionalString(a) + .addRepeatedString(b) + .addRepeatedString(c) + .build(); + + // String should be the one we passed it. + assertSame(a, proto.getOptionalString()); + assertSame(b, proto.getRepeatedString(0)); + assertSame(c, proto.getRepeatedString(1)); + + + // There's no way to directly observe that the ByteString is cached + // correctly on serialization, but we can observe that it had to recompute + // the string after serialization. + proto.toByteString(); + String aPrime = proto.getOptionalString(); + assertNotSame(a, aPrime); + assertEquals(a, aPrime); + String bPrime = proto.getRepeatedString(0); + assertNotSame(b, bPrime); + assertEquals(b, bPrime); + String cPrime = proto.getRepeatedString(1); + assertNotSame(c, cPrime); + assertEquals(c, cPrime); + + // And now the string should stay cached. + assertSame(aPrime, proto.getOptionalString()); + assertSame(bPrime, proto.getRepeatedString(0)); + assertSame(cPrime, proto.getRepeatedString(1)); + } + + public void testNoStringCachingIfOnlyBytesAccessed() throws Exception { + UnittestProto.TestAllTypes proto = + UnittestProto.TestAllTypes.parseFrom(encodedTestAllTypes); + ByteString optional = proto.getOptionalStringBytes(); + assertSame(optional, proto.getOptionalStringBytes()); + assertSame(optional, proto.toBuilder().getOptionalStringBytes()); + + ByteString repeated0 = proto.getRepeatedStringBytes(0); + ByteString repeated1 = proto.getRepeatedStringBytes(1); + assertSame(repeated0, proto.getRepeatedStringBytes(0)); + assertSame(repeated1, proto.getRepeatedStringBytes(1)); + assertSame(repeated0, proto.toBuilder().getRepeatedStringBytes(0)); + assertSame(repeated1, proto.toBuilder().getRepeatedStringBytes(1)); + } +} diff --git a/java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java b/java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java new file mode 100644 index 0000000..471acbb --- /dev/null +++ b/java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java @@ -0,0 +1,85 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar; +import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime; +import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo; + +import junit.framework.TestCase; + +/** + * Test generate equal and hash methods for the lite runtime. + * + * @author pbogle@google.com Phil Bogle + */ +public class LiteEqualsAndHashTest extends TestCase { + + public void testEquals() throws Exception { + // Since the generated equals and hashCode methods for lite messages are a + // mostly complete subset of those for regular messages, we can mostly assume + // that the generated methods are already thoroughly tested by the regular tests. + + // This test mostly just verifies is that a proto with + // optimize_for = LITE_RUNTIME and java_generates_equals_and_hash_compiles + // correctly when linked only against the lite library. + + // We do however do some basic testing to make sure that equals is actually + // overriden to test for value equality rather than simple object equality. + + // Check that two identical objs are equal. + Foo foo1a = Foo.newBuilder() + .setValue(1) + .addBar(Bar.newBuilder().setName("foo1")) + .build(); + Foo foo1b = Foo.newBuilder() + .setValue(1) + .addBar(Bar.newBuilder().setName("foo1")) + .build(); + Foo foo2 = Foo.newBuilder() + .setValue(1) + .addBar(Bar.newBuilder().setName("foo2")) + .build(); + + // Check that equals is doing value rather than object equality. + assertEquals(foo1a, foo1b); + assertEquals(foo1a.hashCode(), foo1b.hashCode()); + + // Check that a diffeent object is not equal. + assertFalse(foo1a.equals(foo2)); + + // Check that two objects which have different types but the same field values are not + // considered to be equal. + Bar bar = Bar.newBuilder().setName("bar").build(); + BarPrime barPrime = BarPrime.newBuilder().setName("bar").build(); + assertFalse(bar.equals(barPrime)); + } +} diff --git a/java/src/test/java/com/google/protobuf/LiteTest.java b/java/src/test/java/com/google/protobuf/LiteTest.java index 728bad9..839694d 100644 --- a/java/src/test/java/com/google/protobuf/LiteTest.java +++ b/java/src/test/java/com/google/protobuf/LiteTest.java @@ -37,6 +37,11 @@ import com.google.protobuf.UnittestLite.TestNestedExtensionLite; import junit.framework.TestCase; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + /** * Test lite runtime. * @@ -113,4 +118,31 @@ public class LiteTest extends TestCase { assertEquals(7, message2.getExtension( UnittestLite.optionalNestedMessageExtensionLite).getBb()); } + + public void testSerialize() throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + TestAllTypesLite expected = + TestAllTypesLite.newBuilder() + .setOptionalInt32(123) + .addRepeatedString("hello") + .setOptionalNestedMessage( + TestAllTypesLite.NestedMessage.newBuilder().setBb(7)) + .build(); + ObjectOutputStream out = new ObjectOutputStream(baos); + try { + out.writeObject(expected); + } finally { + out.close(); + } + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream in = new ObjectInputStream(bais); + TestAllTypesLite actual = (TestAllTypesLite) in.readObject(); + assertEquals(expected.getOptionalInt32(), actual.getOptionalInt32()); + assertEquals(expected.getRepeatedStringCount(), + actual.getRepeatedStringCount()); + assertEquals(expected.getRepeatedString(0), + actual.getRepeatedString(0)); + assertEquals(expected.getOptionalNestedMessage().getBb(), + actual.getOptionalNestedMessage().getBb()); + } } diff --git a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java new file mode 100644 index 0000000..deee1ee --- /dev/null +++ b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java @@ -0,0 +1,396 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import junit.framework.TestCase; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.List; +import java.util.NoSuchElementException; + +/** + * Test {@link LiteralByteString} by setting up a reference string in {@link #setUp()}. + * This class is designed to be extended for testing extensions of {@link LiteralByteString} + * such as {@link BoundedByteString}, see {@link BoundedByteStringTest}. + * + * @author carlanton@google.com (Carl Haverl) + */ +public class LiteralByteStringTest extends TestCase { + protected static final String UTF_8 = "UTF-8"; + + protected String classUnderTest; + protected byte[] referenceBytes; + protected ByteString stringUnderTest; + protected int expectedHashCode; + + @Override + protected void setUp() throws Exception { + classUnderTest = "LiteralByteString"; + referenceBytes = ByteStringTest.getTestBytes(1234, 11337766L); + stringUnderTest = ByteString.copyFrom(referenceBytes); + expectedHashCode = 331161852; + } + + public void testExpectedType() { + String actualClassName = getActualClassName(stringUnderTest); + assertEquals(classUnderTest + " should match type exactly", classUnderTest, actualClassName); + } + + protected String getActualClassName(Object object) { + String actualClassName = object.getClass().getName(); + actualClassName = actualClassName.substring(actualClassName.lastIndexOf('.') + 1); + return actualClassName; + } + + public void testByteAt() { + boolean stillEqual = true; + for (int i = 0; stillEqual && i < referenceBytes.length; ++i) { + stillEqual = (referenceBytes[i] == stringUnderTest.byteAt(i)); + } + assertTrue(classUnderTest + " must capture the right bytes", stillEqual); + } + + public void testByteIterator() { + boolean stillEqual = true; + ByteString.ByteIterator iter = stringUnderTest.iterator(); + for (int i = 0; stillEqual && i < referenceBytes.length; ++i) { + stillEqual = (iter.hasNext() && referenceBytes[i] == iter.nextByte()); + } + assertTrue(classUnderTest + " must capture the right bytes", stillEqual); + assertFalse(classUnderTest + " must have exhausted the itertor", iter.hasNext()); + + try { + iter.nextByte(); + fail("Should have thrown an exception."); + } catch (NoSuchElementException e) { + // This is success + } + } + + public void testByteIterable() { + boolean stillEqual = true; + int j = 0; + for (byte quantum : stringUnderTest) { + stillEqual = (referenceBytes[j] == quantum); + ++j; + } + assertTrue(classUnderTest + " must capture the right bytes as Bytes", stillEqual); + assertEquals(classUnderTest + " iterable character count", referenceBytes.length, j); + } + + public void testSize() { + assertEquals(classUnderTest + " must have the expected size", referenceBytes.length, + stringUnderTest.size()); + } + + public void testGetTreeDepth() { + assertEquals(classUnderTest + " must have depth 0", 0, stringUnderTest.getTreeDepth()); + } + + public void testIsBalanced() { + assertTrue(classUnderTest + " is technically balanced", stringUnderTest.isBalanced()); + } + + public void testCopyTo_ByteArrayOffsetLength() { + int destinationOffset = 50; + int length = 100; + byte[] destination = new byte[destinationOffset + length]; + int sourceOffset = 213; + stringUnderTest.copyTo(destination, sourceOffset, destinationOffset, length); + boolean stillEqual = true; + for (int i = 0; stillEqual && i < length; ++i) { + stillEqual = referenceBytes[i + sourceOffset] == destination[i + destinationOffset]; + } + assertTrue(classUnderTest + ".copyTo(4 arg) must give the expected bytes", stillEqual); + } + + public void testCopyTo_ByteArrayOffsetLengthErrors() { + int destinationOffset = 50; + int length = 100; + byte[] destination = new byte[destinationOffset + length]; + + try { + // Copy one too many bytes + stringUnderTest.copyTo(destination, stringUnderTest.size() + 1 - length, + destinationOffset, length); + fail("Should have thrown an exception when copying too many bytes of a " + + classUnderTest); + } catch (IndexOutOfBoundsException expected) { + // This is success + } + + try { + // Copy with illegal negative sourceOffset + stringUnderTest.copyTo(destination, -1, destinationOffset, length); + fail("Should have thrown an exception when given a negative sourceOffset in " + + classUnderTest); + } catch (IndexOutOfBoundsException expected) { + // This is success + } + + try { + // Copy with illegal negative destinationOffset + stringUnderTest.copyTo(destination, 0, -1, length); + fail("Should have thrown an exception when given a negative destinationOffset in " + + classUnderTest); + } catch (IndexOutOfBoundsException expected) { + // This is success + } + + try { + // Copy with illegal negative size + stringUnderTest.copyTo(destination, 0, 0, -1); + fail("Should have thrown an exception when given a negative size in " + + classUnderTest); + } catch (IndexOutOfBoundsException expected) { + // This is success + } + + try { + // Copy with illegal too-large sourceOffset + stringUnderTest.copyTo(destination, 2 * stringUnderTest.size(), 0, length); + fail("Should have thrown an exception when the destinationOffset is too large in " + + classUnderTest); + } catch (IndexOutOfBoundsException expected) { + // This is success + } + + try { + // Copy with illegal too-large destinationOffset + stringUnderTest.copyTo(destination, 0, 2 * destination.length, length); + fail("Should have thrown an exception when the destinationOffset is too large in " + + classUnderTest); + } catch (IndexOutOfBoundsException expected) { + // This is success + } + } + + public void testCopyTo_ByteBuffer() { + ByteBuffer myBuffer = ByteBuffer.allocate(referenceBytes.length); + stringUnderTest.copyTo(myBuffer); + assertTrue(classUnderTest + ".copyTo(ByteBuffer) must give back the same bytes", + Arrays.equals(referenceBytes, myBuffer.array())); + } + + public void testAsReadOnlyByteBuffer() { + ByteBuffer byteBuffer = stringUnderTest.asReadOnlyByteBuffer(); + byte[] roundTripBytes = new byte[referenceBytes.length]; + assertTrue(byteBuffer.remaining() == referenceBytes.length); + assertTrue(byteBuffer.isReadOnly()); + byteBuffer.get(roundTripBytes); + assertTrue(classUnderTest + ".asReadOnlyByteBuffer() must give back the same bytes", + Arrays.equals(referenceBytes, roundTripBytes)); + } + + public void testAsReadOnlyByteBufferList() { + List byteBuffers = stringUnderTest.asReadOnlyByteBufferList(); + int bytesSeen = 0; + byte[] roundTripBytes = new byte[referenceBytes.length]; + for (ByteBuffer byteBuffer : byteBuffers) { + int thisLength = byteBuffer.remaining(); + assertTrue(byteBuffer.isReadOnly()); + assertTrue(bytesSeen + thisLength <= referenceBytes.length); + byteBuffer.get(roundTripBytes, bytesSeen, thisLength); + bytesSeen += thisLength; + } + assertTrue(bytesSeen == referenceBytes.length); + assertTrue(classUnderTest + ".asReadOnlyByteBufferTest() must give back the same bytes", + Arrays.equals(referenceBytes, roundTripBytes)); + } + + public void testToByteArray() { + byte[] roundTripBytes = stringUnderTest.toByteArray(); + assertTrue(classUnderTest + ".toByteArray() must give back the same bytes", + Arrays.equals(referenceBytes, roundTripBytes)); + } + + public void testWriteTo() throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + stringUnderTest.writeTo(bos); + byte[] roundTripBytes = bos.toByteArray(); + assertTrue(classUnderTest + ".writeTo() must give back the same bytes", + Arrays.equals(referenceBytes, roundTripBytes)); + } + + public void testWriteTo_mutating() throws IOException { + OutputStream os = new OutputStream() { + @Override + public void write(byte[] b, int off, int len) { + for (int x = 0; x < len; ++x) { + b[off + x] = (byte) 0; + } + } + + @Override + public void write(int b) { + // Purposefully left blank. + } + }; + + stringUnderTest.writeTo(os); + byte[] newBytes = stringUnderTest.toByteArray(); + assertTrue(classUnderTest + ".writeTo() must not grant access to underlying array", + Arrays.equals(referenceBytes, newBytes)); + } + + public void testNewOutput() throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ByteString.Output output = ByteString.newOutput(); + stringUnderTest.writeTo(output); + assertEquals("Output Size returns correct result", + output.size(), stringUnderTest.size()); + output.writeTo(bos); + assertTrue("Output.writeTo() must give back the same bytes", + Arrays.equals(referenceBytes, bos.toByteArray())); + + // write the output stream to itself! This should cause it to double + output.writeTo(output); + assertEquals("Writing an output stream to itself is successful", + stringUnderTest.concat(stringUnderTest), output.toByteString()); + + output.reset(); + assertEquals("Output.reset() resets the output", 0, output.size()); + assertEquals("Output.reset() resets the output", + ByteString.EMPTY, output.toByteString()); + + } + + public void testToString() throws UnsupportedEncodingException { + String testString = "I love unicode \u1234\u5678 characters"; + LiteralByteString unicode = new LiteralByteString(testString.getBytes(UTF_8)); + String roundTripString = unicode.toString(UTF_8); + assertEquals(classUnderTest + " unicode must match", testString, roundTripString); + } + + public void testEquals() { + assertEquals(classUnderTest + " must not equal null", false, stringUnderTest.equals(null)); + assertEquals(classUnderTest + " must equal self", stringUnderTest, stringUnderTest); + assertFalse(classUnderTest + " must not equal the empty string", + stringUnderTest.equals(ByteString.EMPTY)); + assertEquals(classUnderTest + " empty strings must be equal", + new LiteralByteString(new byte[]{}), stringUnderTest.substring(55, 55)); + assertEquals(classUnderTest + " must equal another string with the same value", + stringUnderTest, new LiteralByteString(referenceBytes)); + + byte[] mungedBytes = new byte[referenceBytes.length]; + System.arraycopy(referenceBytes, 0, mungedBytes, 0, referenceBytes.length); + mungedBytes[mungedBytes.length - 5] ^= 0xFF; + assertFalse(classUnderTest + " must not equal every string with the same length", + stringUnderTest.equals(new LiteralByteString(mungedBytes))); + } + + public void testHashCode() { + int hash = stringUnderTest.hashCode(); + assertEquals(classUnderTest + " must have expected hashCode", expectedHashCode, hash); + } + + public void testPeekCachedHashCode() { + assertEquals(classUnderTest + ".peekCachedHashCode() should return zero at first", 0, + stringUnderTest.peekCachedHashCode()); + stringUnderTest.hashCode(); + assertEquals(classUnderTest + ".peekCachedHashCode should return zero at first", + expectedHashCode, stringUnderTest.peekCachedHashCode()); + } + + public void testPartialHash() { + // partialHash() is more strenuously tested elsewhere by testing hashes of substrings. + // This test would fail if the expected hash were 1. It's not. + int hash = stringUnderTest.partialHash(stringUnderTest.size(), 0, stringUnderTest.size()); + assertEquals(classUnderTest + ".partialHash() must yield expected hashCode", + expectedHashCode, hash); + } + + public void testNewInput() throws IOException { + InputStream input = stringUnderTest.newInput(); + assertEquals("InputStream.available() returns correct value", + stringUnderTest.size(), input.available()); + boolean stillEqual = true; + for (byte referenceByte : referenceBytes) { + int expectedInt = (referenceByte & 0xFF); + stillEqual = (expectedInt == input.read()); + } + assertEquals("InputStream.available() returns correct value", + 0, input.available()); + assertTrue(classUnderTest + " must give the same bytes from the InputStream", stillEqual); + assertEquals(classUnderTest + " InputStream must now be exhausted", -1, input.read()); + } + + public void testNewInput_skip() throws IOException { + InputStream input = stringUnderTest.newInput(); + int stringSize = stringUnderTest.size(); + int nearEndIndex = stringSize * 2 / 3; + long skipped1 = input.skip(nearEndIndex); + assertEquals("InputStream.skip()", skipped1, nearEndIndex); + assertEquals("InputStream.available()", + stringSize - skipped1, input.available()); + assertTrue("InputStream.mark() is available", input.markSupported()); + input.mark(0); + assertEquals("InputStream.skip(), read()", + stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read()); + assertEquals("InputStream.available()", + stringSize - skipped1 - 1, input.available()); + long skipped2 = input.skip(stringSize); + assertEquals("InputStream.skip() incomplete", + skipped2, stringSize - skipped1 - 1); + assertEquals("InputStream.skip(), no more input", 0, input.available()); + assertEquals("InputStream.skip(), no more input", -1, input.read()); + input.reset(); + assertEquals("InputStream.reset() succeded", + stringSize - skipped1, input.available()); + assertEquals("InputStream.reset(), read()", + stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read()); + } + + public void testNewCodedInput() throws IOException { + CodedInputStream cis = stringUnderTest.newCodedInput(); + byte[] roundTripBytes = cis.readRawBytes(referenceBytes.length); + assertTrue(classUnderTest + " must give the same bytes back from the CodedInputStream", + Arrays.equals(referenceBytes, roundTripBytes)); + assertTrue(classUnderTest + " CodedInputStream must now be exhausted", cis.isAtEnd()); + } + + /** + * Make sure we keep things simple when concatenating with empty. See also + * {@link ByteStringTest#testConcat_empty()}. + */ + public void testConcat_empty() { + assertSame(classUnderTest + " concatenated with empty must give " + classUnderTest, + stringUnderTest.concat(ByteString.EMPTY), stringUnderTest); + assertSame("empty concatenated with " + classUnderTest + " must give " + classUnderTest, + ByteString.EMPTY.concat(stringUnderTest), stringUnderTest); + } +} diff --git a/java/src/test/java/com/google/protobuf/MessageTest.java b/java/src/test/java/com/google/protobuf/MessageTest.java index c2f47eb..747fed7 100644 --- a/java/src/test/java/com/google/protobuf/MessageTest.java +++ b/java/src/test/java/com/google/protobuf/MessageTest.java @@ -38,6 +38,8 @@ import protobuf_unittest.UnittestProto.ForeignMessage; import junit.framework.TestCase; +import java.util.List; + /** * Misc. unit tests for message operations that apply to both generated * and dynamic messages. @@ -310,4 +312,42 @@ public class MessageTest extends TestCase { assertEquals("Message missing required fields: a, b, c", e.getMessage()); } } + + /** Test reading unset repeated message from DynamicMessage. */ + public void testDynamicRepeatedMessageNull() throws Exception { + Descriptors.Descriptor descriptor = TestRequired.getDescriptor(); + DynamicMessage result = + DynamicMessage.newBuilder(TestAllTypes.getDescriptor()) + .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build()) + .build(); + + assertTrue(result.getField(result.getDescriptorForType() + .findFieldByName("repeated_foreign_message")) instanceof List); + assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType() + .findFieldByName("repeated_foreign_message")), 0); + } + + /** Test reading repeated message from DynamicMessage. */ + public void testDynamicRepeatedMessageNotNull() throws Exception { + + TestAllTypes REPEATED_NESTED = + TestAllTypes.newBuilder() + .setOptionalInt32(1) + .setOptionalString("foo") + .setOptionalForeignMessage(ForeignMessage.getDefaultInstance()) + .addRepeatedString("bar") + .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance()) + .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance()) + .build(); + Descriptors.Descriptor descriptor = TestRequired.getDescriptor(); + DynamicMessage result = + DynamicMessage.newBuilder(TestAllTypes.getDescriptor()) + .mergeFrom(DynamicMessage.newBuilder(REPEATED_NESTED).build()) + .build(); + + assertTrue(result.getField(result.getDescriptorForType() + .findFieldByName("repeated_foreign_message")) instanceof List); + assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType() + .findFieldByName("repeated_foreign_message")), 2); + } } diff --git a/java/src/test/java/com/google/protobuf/NestedBuildersTest.java b/java/src/test/java/com/google/protobuf/NestedBuildersTest.java new file mode 100644 index 0000000..f537580 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/NestedBuildersTest.java @@ -0,0 +1,185 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import protobuf_unittest.Vehicle; +import protobuf_unittest.Wheel; + +import junit.framework.TestCase; + +import java.util.List; +import java.util.ArrayList; + +/** + * Test cases that exercise end-to-end use cases involving + * {@link SingleFieldBuilder} and {@link RepeatedFieldBuilder}. + * + * @author jonp@google.com (Jon Perlow) + */ +public class NestedBuildersTest extends TestCase { + + public void testMessagesAndBuilders() { + Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); + vehicleBuilder.addWheelBuilder() + .setRadius(4) + .setWidth(1); + vehicleBuilder.addWheelBuilder() + .setRadius(4) + .setWidth(2); + vehicleBuilder.addWheelBuilder() + .setRadius(4) + .setWidth(3); + vehicleBuilder.addWheelBuilder() + .setRadius(4) + .setWidth(4); + vehicleBuilder.getEngineBuilder() + .setLiters(10); + + Vehicle vehicle = vehicleBuilder.build(); + assertEquals(4, vehicle.getWheelCount()); + for (int i = 0; i < 4; i++) { + Wheel wheel = vehicle.getWheel(i); + assertEquals(4, wheel.getRadius()); + assertEquals(i + 1, wheel.getWidth()); + } + assertEquals(10, vehicle.getEngine().getLiters()); + + for (int i = 0; i < 4; i++) { + vehicleBuilder.getWheelBuilder(i) + .setRadius(5) + .setWidth(i + 10); + } + vehicleBuilder.getEngineBuilder().setLiters(20); + + vehicle = vehicleBuilder.build(); + for (int i = 0; i < 4; i++) { + Wheel wheel = vehicle.getWheel(i); + assertEquals(5, wheel.getRadius()); + assertEquals(i + 10, wheel.getWidth()); + } + assertEquals(20, vehicle.getEngine().getLiters()); + assertTrue(vehicle.hasEngine()); + } + + public void testMessagesAreCached() { + Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); + vehicleBuilder.addWheelBuilder() + .setRadius(1) + .setWidth(2); + vehicleBuilder.addWheelBuilder() + .setRadius(3) + .setWidth(4); + vehicleBuilder.addWheelBuilder() + .setRadius(5) + .setWidth(6); + vehicleBuilder.addWheelBuilder() + .setRadius(7) + .setWidth(8); + + // Make sure messages are cached. + List wheels = new ArrayList(vehicleBuilder.getWheelList()); + for (int i = 0; i < wheels.size(); i++) { + assertSame(wheels.get(i), vehicleBuilder.getWheel(i)); + } + + // Now get builders and check they didn't change. + for (int i = 0; i < wheels.size(); i++) { + vehicleBuilder.getWheel(i); + } + for (int i = 0; i < wheels.size(); i++) { + assertSame(wheels.get(i), vehicleBuilder.getWheel(i)); + } + + // Change just one + vehicleBuilder.getWheelBuilder(3) + .setRadius(20).setWidth(20); + + // Now get wheels and check that only that one changed + for (int i = 0; i < wheels.size(); i++) { + if (i < 3) { + assertSame(wheels.get(i), vehicleBuilder.getWheel(i)); + } else { + assertNotSame(wheels.get(i), vehicleBuilder.getWheel(i)); + } + } + } + + public void testRemove_WithNestedBuilders() { + Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); + vehicleBuilder.addWheelBuilder() + .setRadius(1) + .setWidth(1); + vehicleBuilder.addWheelBuilder() + .setRadius(2) + .setWidth(2); + vehicleBuilder.removeWheel(0); + + assertEquals(1, vehicleBuilder.getWheelCount()); + assertEquals(2, vehicleBuilder.getWheel(0).getRadius()); + } + + public void testRemove_WithNestedMessages() { + Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); + vehicleBuilder.addWheel(Wheel.newBuilder() + .setRadius(1) + .setWidth(1)); + vehicleBuilder.addWheel(Wheel.newBuilder() + .setRadius(2) + .setWidth(2)); + vehicleBuilder.removeWheel(0); + + assertEquals(1, vehicleBuilder.getWheelCount()); + assertEquals(2, vehicleBuilder.getWheel(0).getRadius()); + } + + public void testMerge() { + Vehicle vehicle1 = Vehicle.newBuilder() + .addWheel(Wheel.newBuilder().setRadius(1).build()) + .addWheel(Wheel.newBuilder().setRadius(2).build()) + .build(); + + Vehicle vehicle2 = Vehicle.newBuilder() + .mergeFrom(vehicle1) + .build(); + // List should be the same -- no allocation + assertSame(vehicle1.getWheelList(), vehicle2.getWheelList()); + + Vehicle vehicle3 = vehicle1.toBuilder().build(); + assertSame(vehicle1.getWheelList(), vehicle3.getWheelList()); + } + + public void testGettingBuilderMarksFieldAsHaving() { + Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); + vehicleBuilder.getEngineBuilder(); + Vehicle vehicle = vehicleBuilder.buildPartial(); + assertTrue(vehicle.hasEngine()); + } +} diff --git a/java/src/test/java/com/google/protobuf/ParserTest.java b/java/src/test/java/com/google/protobuf/ParserTest.java new file mode 100644 index 0000000..8cc4693 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/ParserTest.java @@ -0,0 +1,381 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import com.google.protobuf.UnittestLite.TestAllTypesLite; +import com.google.protobuf.UnittestLite.TestPackedExtensionsLite; +import com.google.protobuf.UnittestLite.TestParsingMergeLite; +import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize; +import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize; +import protobuf_unittest.UnittestOptimizeFor; +import protobuf_unittest.UnittestProto.ForeignMessage; +import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestEmptyMessage; +import protobuf_unittest.UnittestProto.TestParsingMerge; +import protobuf_unittest.UnittestProto.TestRequired; +import protobuf_unittest.UnittestProto; + +import junit.framework.TestCase; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Unit test for {@link Parser}. + * + * @author liujisi@google.com (Pherl Liu) + */ +public class ParserTest extends TestCase { + public void testGeneratedMessageParserSingleton() throws Exception { + for (int i = 0; i < 10; i++) { + assertEquals(TestAllTypes.PARSER, + TestUtil.getAllSet().getParserForType()); + } + } + + private void assertRoundTripEquals(MessageLite message, + ExtensionRegistryLite registry) + throws Exception { + final byte[] data = message.toByteArray(); + final int offset = 20; + final int length = data.length; + final int padding = 30; + Parser parser = message.getParserForType(); + assertMessageEquals(message, parser.parseFrom(data, registry)); + assertMessageEquals(message, parser.parseFrom( + generatePaddingArray(data, offset, padding), + offset, length, registry)); + assertMessageEquals(message, parser.parseFrom( + message.toByteString(), registry)); + assertMessageEquals(message, parser.parseFrom( + new ByteArrayInputStream(data), registry)); + assertMessageEquals(message, parser.parseFrom( + CodedInputStream.newInstance(data), registry)); + } + + @SuppressWarnings("unchecked") + private void assertRoundTripEquals(MessageLite message) throws Exception { + final byte[] data = message.toByteArray(); + final int offset = 20; + final int length = data.length; + final int padding = 30; + + Parser parser = + (Parser) message.getParserForType(); + assertMessageEquals(message, parser.parseFrom(data)); + assertMessageEquals(message, parser.parseFrom( + generatePaddingArray(data, offset, padding), + offset, length)); + assertMessageEquals(message, parser.parseFrom(message.toByteString())); + assertMessageEquals(message, parser.parseFrom( + new ByteArrayInputStream(data))); + assertMessageEquals(message, parser.parseFrom( + CodedInputStream.newInstance(data))); + } + + private void assertMessageEquals( + MessageLite expected, MessageLite actual) + throws Exception { + if (expected instanceof Message) { + assertEquals(expected, actual); + } else { + assertEquals(expected.toByteString(), actual.toByteString()); + } + } + + private byte[] generatePaddingArray(byte[] data, int offset, int padding) { + byte[] result = new byte[offset + data.length + padding]; + System.arraycopy(data, 0, result, offset, data.length); + return result; + } + + public void testNormalMessage() throws Exception { + assertRoundTripEquals(TestUtil.getAllSet()); + } + + + public void testParsePartial() throws Exception { + assertParsePartial(TestRequired.PARSER, + TestRequired.newBuilder().setA(1).buildPartial()); + } + + private void assertParsePartial( + Parser parser, T partialMessage) throws Exception { + final String errorString = + "Should throw exceptions when the parsed message isn't initialized."; + + // parsePartialFrom should pass. + byte[] data = partialMessage.toByteArray(); + assertEquals(partialMessage, parser.parsePartialFrom(data)); + assertEquals(partialMessage, parser.parsePartialFrom( + partialMessage.toByteString())); + assertEquals(partialMessage, parser.parsePartialFrom( + new ByteArrayInputStream(data))); + assertEquals(partialMessage, parser.parsePartialFrom( + CodedInputStream.newInstance(data))); + + // parseFrom(ByteArray) + try { + parser.parseFrom(partialMessage.toByteArray()); + fail(errorString); + } catch (InvalidProtocolBufferException e) { + // pass. + } + + // parseFrom(ByteString) + try { + parser.parseFrom(partialMessage.toByteString()); + fail(errorString); + } catch (InvalidProtocolBufferException e) { + // pass. + } + + // parseFrom(InputStream) + try { + parser.parseFrom(new ByteArrayInputStream(partialMessage.toByteArray())); + fail(errorString); + } catch (IOException e) { + // pass. + } + + // parseFrom(CodedInputStream) + try { + parser.parseFrom(CodedInputStream.newInstance( + partialMessage.toByteArray())); + fail(errorString); + } catch (IOException e) { + // pass. + } + } + + public void testParseExtensions() throws Exception { + assertRoundTripEquals(TestUtil.getAllExtensionsSet(), + TestUtil.getExtensionRegistry()); + assertRoundTripEquals(TestUtil.getAllLiteExtensionsSet(), + TestUtil.getExtensionRegistryLite()); + } + + public void testParsePacked() throws Exception { + assertRoundTripEquals(TestUtil.getPackedSet()); + assertRoundTripEquals(TestUtil.getPackedExtensionsSet(), + TestUtil.getExtensionRegistry()); + assertRoundTripEquals(TestUtil.getLitePackedExtensionsSet(), + TestUtil.getExtensionRegistryLite()); + } + + public void testParseDelimitedTo() throws Exception { + // Write normal Message. + TestAllTypes normalMessage = TestUtil.getAllSet(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + normalMessage.writeDelimitedTo(output); + + // Write MessageLite with packed extension fields. + TestPackedExtensionsLite packedMessage = + TestUtil.getLitePackedExtensionsSet(); + packedMessage.writeDelimitedTo(output); + + InputStream input = new ByteArrayInputStream(output.toByteArray()); + assertMessageEquals( + normalMessage, + normalMessage.getParserForType().parseDelimitedFrom(input)); + assertMessageEquals( + packedMessage, + packedMessage.getParserForType().parseDelimitedFrom( + input, TestUtil.getExtensionRegistryLite())); + } + + public void testParseUnknownFields() throws Exception { + // All fields will be treated as unknown fields in emptyMessage. + TestEmptyMessage emptyMessage = TestEmptyMessage.PARSER.parseFrom( + TestUtil.getAllSet().toByteString()); + assertEquals( + TestUtil.getAllSet().toByteString(), + emptyMessage.toByteString()); + } + + + public void testOptimizeForSize() throws Exception { + TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder(); + builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build()); + builder.setExtension(TestOptimizedForSize.testExtension, 56); + builder.setExtension(TestOptimizedForSize.testExtension2, + TestRequiredOptimizedForSize.newBuilder().setX(78).build()); + + TestOptimizedForSize message = builder.build(); + ExtensionRegistry registry = ExtensionRegistry.newInstance(); + UnittestOptimizeFor.registerAllExtensions(registry); + + assertRoundTripEquals(message, registry); + } + + /** Helper method for {@link #testParsingMerge()}.*/ + private void assertMessageMerged(TestAllTypes allTypes) + throws Exception { + assertEquals(3, allTypes.getOptionalInt32()); + assertEquals(2, allTypes.getOptionalInt64()); + assertEquals("hello", allTypes.getOptionalString()); + } + + /** Helper method for {@link #testParsingMergeLite()}.*/ + private void assertMessageMerged(TestAllTypesLite allTypes) + throws Exception { + assertEquals(3, allTypes.getOptionalInt32()); + assertEquals(2, allTypes.getOptionalInt64()); + assertEquals("hello", allTypes.getOptionalString()); + } + + public void testParsingMerge() throws Exception { + // Build messages. + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + TestAllTypes msg1 = builder.setOptionalInt32(1).build(); + builder.clear(); + TestAllTypes msg2 = builder.setOptionalInt64(2).build(); + builder.clear(); + TestAllTypes msg3 = builder.setOptionalInt32(3) + .setOptionalString("hello").build(); + + // Build groups. + TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 = + TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder() + .setField1(msg1).build(); + TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 = + TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder() + .setField1(msg2).build(); + TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 = + TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder() + .setField1(msg3).build(); + TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 = + TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder() + .setField1(msg1).build(); + TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 = + TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder() + .setField1(msg2).build(); + TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 = + TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder() + .setField1(msg3).build(); + + // Assign and serialize RepeatedFieldsGenerator. + ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder() + .addField1(msg1).addField1(msg2).addField1(msg3) + .addField2(msg1).addField2(msg2).addField2(msg3) + .addField3(msg1).addField3(msg2).addField3(msg3) + .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3) + .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3) + .addExt1(msg1).addExt1(msg2).addExt1(msg3) + .addExt2(msg1).addExt2(msg2).addExt2(msg3) + .build().toByteString(); + + // Parse TestParsingMerge. + ExtensionRegistry registry = ExtensionRegistry.newInstance(); + UnittestProto.registerAllExtensions(registry); + TestParsingMerge parsingMerge = + TestParsingMerge.PARSER.parseFrom(data, registry); + + // Required and optional fields should be merged. + assertMessageMerged(parsingMerge.getRequiredAllTypes()); + assertMessageMerged(parsingMerge.getOptionalAllTypes()); + assertMessageMerged( + parsingMerge.getOptionalGroup().getOptionalGroupAllTypes()); + assertMessageMerged(parsingMerge.getExtension( + TestParsingMerge.optionalExt)); + + // Repeated fields should not be merged. + assertEquals(3, parsingMerge.getRepeatedAllTypesCount()); + assertEquals(3, parsingMerge.getRepeatedGroupCount()); + assertEquals(3, parsingMerge.getExtensionCount( + TestParsingMerge.repeatedExt)); + } + + public void testParsingMergeLite() throws Exception { + // Build messages. + TestAllTypesLite.Builder builder = + TestAllTypesLite.newBuilder(); + TestAllTypesLite msg1 = builder.setOptionalInt32(1).build(); + builder.clear(); + TestAllTypesLite msg2 = builder.setOptionalInt64(2).build(); + builder.clear(); + TestAllTypesLite msg3 = builder.setOptionalInt32(3) + .setOptionalString("hello").build(); + + // Build groups. + TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG1 = + TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder() + .setField1(msg1).build(); + TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG2 = + TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder() + .setField1(msg2).build(); + TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG3 = + TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder() + .setField1(msg3).build(); + TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG1 = + TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder() + .setField1(msg1).build(); + TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG2 = + TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder() + .setField1(msg2).build(); + TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG3 = + TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder() + .setField1(msg3).build(); + + // Assign and serialize RepeatedFieldsGenerator. + ByteString data = TestParsingMergeLite.RepeatedFieldsGenerator.newBuilder() + .addField1(msg1).addField1(msg2).addField1(msg3) + .addField2(msg1).addField2(msg2).addField2(msg3) + .addField3(msg1).addField3(msg2).addField3(msg3) + .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3) + .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3) + .addExt1(msg1).addExt1(msg2).addExt1(msg3) + .addExt2(msg1).addExt2(msg2).addExt2(msg3) + .build().toByteString(); + + // Parse TestParsingMergeLite. + ExtensionRegistry registry = ExtensionRegistry.newInstance(); + UnittestLite.registerAllExtensions(registry); + TestParsingMergeLite parsingMerge = + TestParsingMergeLite.PARSER.parseFrom(data, registry); + + // Required and optional fields should be merged. + assertMessageMerged(parsingMerge.getRequiredAllTypes()); + assertMessageMerged(parsingMerge.getOptionalAllTypes()); + assertMessageMerged( + parsingMerge.getOptionalGroup().getOptionalGroupAllTypes()); + assertMessageMerged(parsingMerge.getExtension( + TestParsingMergeLite.optionalExt)); + + // Repeated fields should not be merged. + assertEquals(3, parsingMerge.getRepeatedAllTypesCount()); + assertEquals(3, parsingMerge.getRepeatedGroupCount()); + assertEquals(3, parsingMerge.getExtensionCount( + TestParsingMergeLite.repeatedExt)); + } +} diff --git a/java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java b/java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java new file mode 100644 index 0000000..cdcdcb2 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java @@ -0,0 +1,190 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder; + +import junit.framework.TestCase; + +import java.util.Collections; +import java.util.List; + +/** + * Tests for {@link RepeatedFieldBuilder}. This tests basic functionality. + * More extensive testing is provided via other tests that exercise the + * builder. + * + * @author jonp@google.com (Jon Perlow) + */ +public class RepeatedFieldBuilderTest extends TestCase { + + public void testBasicUse() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + RepeatedFieldBuilder builder = newRepeatedFieldBuilder(mockParent); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); + assertEquals(0, builder.getMessage(0).getOptionalInt32()); + assertEquals(1, builder.getMessage(1).getOptionalInt32()); + + List list = builder.build(); + assertEquals(2, list.size()); + assertEquals(0, list.get(0).getOptionalInt32()); + assertEquals(1, list.get(1).getOptionalInt32()); + assertIsUnmodifiable(list); + + // Make sure it doesn't change. + List list2 = builder.build(); + assertSame(list, list2); + assertEquals(0, mockParent.getInvalidationCount()); + } + + public void testGoingBackAndForth() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + RepeatedFieldBuilder builder = newRepeatedFieldBuilder(mockParent); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); + assertEquals(0, builder.getMessage(0).getOptionalInt32()); + assertEquals(1, builder.getMessage(1).getOptionalInt32()); + + // Convert to list + List list = builder.build(); + assertEquals(2, list.size()); + assertEquals(0, list.get(0).getOptionalInt32()); + assertEquals(1, list.get(1).getOptionalInt32()); + assertIsUnmodifiable(list); + + // Update 0th item + assertEquals(0, mockParent.getInvalidationCount()); + builder.getBuilder(0).setOptionalString("foo"); + assertEquals(1, mockParent.getInvalidationCount()); + list = builder.build(); + assertEquals(2, list.size()); + assertEquals(0, list.get(0).getOptionalInt32()); + assertEquals("foo", list.get(0).getOptionalString()); + assertEquals(1, list.get(1).getOptionalInt32()); + assertIsUnmodifiable(list); + assertEquals(1, mockParent.getInvalidationCount()); + } + + public void testVariousMethods() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + RepeatedFieldBuilder builder = newRepeatedFieldBuilder(mockParent); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(2).build()); + builder.addBuilder(0, TestAllTypes.getDefaultInstance()) + .setOptionalInt32(0); + builder.addBuilder(TestAllTypes.getDefaultInstance()).setOptionalInt32(3); + + assertEquals(0, builder.getMessage(0).getOptionalInt32()); + assertEquals(1, builder.getMessage(1).getOptionalInt32()); + assertEquals(2, builder.getMessage(2).getOptionalInt32()); + assertEquals(3, builder.getMessage(3).getOptionalInt32()); + + assertEquals(0, mockParent.getInvalidationCount()); + List messages = builder.build(); + assertEquals(4, messages.size()); + assertSame(messages, builder.build()); // expect same list + + // Remove a message. + builder.remove(2); + assertEquals(1, mockParent.getInvalidationCount()); + assertEquals(3, builder.getCount()); + assertEquals(0, builder.getMessage(0).getOptionalInt32()); + assertEquals(1, builder.getMessage(1).getOptionalInt32()); + assertEquals(3, builder.getMessage(2).getOptionalInt32()); + + // Remove a builder. + builder.remove(0); + assertEquals(1, mockParent.getInvalidationCount()); + assertEquals(2, builder.getCount()); + assertEquals(1, builder.getMessage(0).getOptionalInt32()); + assertEquals(3, builder.getMessage(1).getOptionalInt32()); + + // Test clear. + builder.clear(); + assertEquals(1, mockParent.getInvalidationCount()); + assertEquals(0, builder.getCount()); + assertTrue(builder.isEmpty()); + } + + public void testLists() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + RepeatedFieldBuilder builder = newRepeatedFieldBuilder(mockParent); + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); + builder.addMessage(0, + TestAllTypes.newBuilder().setOptionalInt32(0).build()); + assertEquals(0, builder.getMessage(0).getOptionalInt32()); + assertEquals(1, builder.getMessage(1).getOptionalInt32()); + + // Use list of builders. + List builders = builder.getBuilderList(); + assertEquals(0, builders.get(0).getOptionalInt32()); + assertEquals(1, builders.get(1).getOptionalInt32()); + builders.get(0).setOptionalInt32(10); + builders.get(1).setOptionalInt32(11); + + // Use list of protos + List protos = builder.getMessageList(); + assertEquals(10, protos.get(0).getOptionalInt32()); + assertEquals(11, protos.get(1).getOptionalInt32()); + + // Add an item to the builders and verify it's updated in both + builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(12).build()); + assertEquals(3, builders.size()); + assertEquals(3, protos.size()); + } + + private void assertIsUnmodifiable(List list) { + if (list == Collections.emptyList()) { + // OKAY -- Need to check this b/c EmptyList allows you to call clear. + } else { + try { + list.clear(); + fail("List wasn't immutable"); + } catch (UnsupportedOperationException e) { + // good + } + } + } + + private RepeatedFieldBuilder + newRepeatedFieldBuilder(GeneratedMessage.BuilderParent parent) { + return new RepeatedFieldBuilder(Collections.emptyList(), false, + parent, false); + } +} diff --git a/java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java b/java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java new file mode 100644 index 0000000..06707a2 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java @@ -0,0 +1,97 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.io.UnsupportedEncodingException; +import java.util.Iterator; + +/** + * This class tests {@link RopeByteString#substring(int, int)} by inheriting the tests from + * {@link LiteralByteStringTest}. Only a couple of methods are overridden. + * + * @author carlanton@google.com (Carl Haverl) + */ +public class RopeByteStringSubstringTest extends LiteralByteStringTest { + + @Override + protected void setUp() throws Exception { + classUnderTest = "RopeByteString"; + byte[] sourceBytes = ByteStringTest.getTestBytes(22341, 22337766L); + Iterator iter = ByteStringTest.makeConcretePieces(sourceBytes).iterator(); + ByteString sourceString = iter.next(); + while (iter.hasNext()) { + sourceString = sourceString.concat(iter.next()); + } + + int from = 1130; + int to = sourceBytes.length - 5555; + stringUnderTest = sourceString.substring(from, to); + referenceBytes = new byte[to - from]; + System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from); + expectedHashCode = -1259260680; + } + + @Override + public void testGetTreeDepth() { + assertEquals(classUnderTest + " must have the expected tree depth", + 3, stringUnderTest.getTreeDepth()); + } + + @Override + public void testToString() throws UnsupportedEncodingException { + String sourceString = "I love unicode \u1234\u5678 characters"; + ByteString sourceByteString = ByteString.copyFromUtf8(sourceString); + int copies = 250; + + // By building the RopeByteString by concatenating, this is actually a fairly strenuous test. + StringBuilder builder = new StringBuilder(copies * sourceString.length()); + ByteString unicode = ByteString.EMPTY; + for (int i = 0; i < copies; ++i) { + builder.append(sourceString); + unicode = RopeByteString.concatenate(unicode, sourceByteString); + } + String testString = builder.toString(); + + // Do the substring part + testString = testString.substring(2, testString.length() - 6); + unicode = unicode.substring(2, unicode.size() - 6); + + assertEquals(classUnderTest + " from string must have the expected type", + classUnderTest, getActualClassName(unicode)); + String roundTripString = unicode.toString(UTF_8); + assertEquals(classUnderTest + " unicode bytes must match", + testString, roundTripString); + ByteString flatString = ByteString.copyFromUtf8(testString); + assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode); + assertEquals(classUnderTest + " string must must have same hashCode as the flat string", + flatString.hashCode(), unicode.hashCode()); + } +} diff --git a/java/src/test/java/com/google/protobuf/RopeByteStringTest.java b/java/src/test/java/com/google/protobuf/RopeByteStringTest.java new file mode 100644 index 0000000..15f660d --- /dev/null +++ b/java/src/test/java/com/google/protobuf/RopeByteStringTest.java @@ -0,0 +1,115 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.Iterator; + +/** + * This class tests {@link RopeByteString} by inheriting the tests from + * {@link LiteralByteStringTest}. Only a couple of methods are overridden. + * + *

            A full test of the result of {@link RopeByteString#substring(int, int)} is found in the + * separate class {@link RopeByteStringSubstringTest}. + * + * @author carlanton@google.com (Carl Haverl) + */ +public class RopeByteStringTest extends LiteralByteStringTest { + + @Override + protected void setUp() throws Exception { + classUnderTest = "RopeByteString"; + referenceBytes = ByteStringTest.getTestBytes(22341, 22337766L); + Iterator iter = ByteStringTest.makeConcretePieces(referenceBytes).iterator(); + stringUnderTest = iter.next(); + while (iter.hasNext()) { + stringUnderTest = stringUnderTest.concat(iter.next()); + } + expectedHashCode = -1214197238; + } + + @Override + public void testGetTreeDepth() { + assertEquals(classUnderTest + " must have the expected tree depth", + 4, stringUnderTest.getTreeDepth()); + } + + public void testBalance() { + int numberOfPieces = 10000; + int pieceSize = 64; + byte[] testBytes = ByteStringTest.getTestBytes(numberOfPieces * pieceSize, 113377L); + + // Build up a big ByteString from smaller pieces to force a rebalance + ByteString concatenated = ByteString.EMPTY; + for (int i = 0; i < numberOfPieces; ++i) { + concatenated = concatenated.concat(ByteString.copyFrom(testBytes, i * pieceSize, pieceSize)); + } + + assertEquals(classUnderTest + " from string must have the expected type", + classUnderTest, getActualClassName(concatenated)); + assertTrue(classUnderTest + " underlying bytes must match after balancing", + Arrays.equals(testBytes, concatenated.toByteArray())); + ByteString testString = ByteString.copyFrom(testBytes); + assertTrue(classUnderTest + " balanced string must equal flat string", + concatenated.equals(testString)); + assertTrue(classUnderTest + " flat string must equal balanced string", + testString.equals(concatenated)); + assertEquals(classUnderTest + " balanced string must have same hash code as flat string", + testString.hashCode(), concatenated.hashCode()); + } + + @Override + public void testToString() throws UnsupportedEncodingException { + String sourceString = "I love unicode \u1234\u5678 characters"; + ByteString sourceByteString = ByteString.copyFromUtf8(sourceString); + int copies = 250; + + // By building the RopeByteString by concatenating, this is actually a fairly strenuous test. + StringBuilder builder = new StringBuilder(copies * sourceString.length()); + ByteString unicode = ByteString.EMPTY; + for (int i = 0; i < copies; ++i) { + builder.append(sourceString); + unicode = RopeByteString.concatenate(unicode, sourceByteString); + } + String testString = builder.toString(); + + assertEquals(classUnderTest + " from string must have the expected type", + classUnderTest, getActualClassName(unicode)); + String roundTripString = unicode.toString(UTF_8); + assertEquals(classUnderTest + " unicode bytes must match", + testString, roundTripString); + ByteString flatString = ByteString.copyFromUtf8(testString); + assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode); + assertEquals(classUnderTest + " string must must have same hashCode as the flat string", + flatString.hashCode(), unicode.hashCode()); + } +} diff --git a/java/src/test/java/com/google/protobuf/ServiceTest.java b/java/src/test/java/com/google/protobuf/ServiceTest.java index e10322d..4be84f5 100644 --- a/java/src/test/java/com/google/protobuf/ServiceTest.java +++ b/java/src/test/java/com/google/protobuf/ServiceTest.java @@ -205,12 +205,6 @@ public class ServiceTest extends TestCase { MethodDescriptor fooMethod = ServiceWithNoOuter.getDescriptor().findMethodByName("Foo"); MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance(); - RpcCallback callback = new RpcCallback() { - public void run(Message parameter) { - // No reason this should be run. - fail(); - } - }; TestAllTypes expectedResponse = TestAllTypes.getDefaultInstance(); EasyMock.expect(impl.foo(EasyMock.same(controller), EasyMock.same(request))) @@ -250,6 +244,14 @@ public class ServiceTest extends TestCase { // make assumptions, so I'm just going to accept any character as the // separator. assertTrue(fullName.startsWith(outerName)); + + if (!Service.class.isAssignableFrom(innerClass) && + !Message.class.isAssignableFrom(innerClass) && + !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) { + // Ignore any classes not generated by the base code generator. + continue; + } + innerClassNames.add(fullName.substring(outerName.length() + 1)); } diff --git a/java/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java b/java/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java new file mode 100644 index 0000000..5c2f7e7 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java @@ -0,0 +1,155 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder; + +import junit.framework.TestCase; + +/** + * Tests for {@link SingleFieldBuilder}. This tests basic functionality. + * More extensive testing is provided via other tests that exercise the + * builder. + * + * @author jonp@google.com (Jon Perlow) + */ +public class SingleFieldBuilderTest extends TestCase { + + public void testBasicUseAndInvalidations() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + SingleFieldBuilder builder = + new SingleFieldBuilder( + TestAllTypes.getDefaultInstance(), + mockParent, + false); + assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); + assertEquals(TestAllTypes.getDefaultInstance(), + builder.getBuilder().buildPartial()); + assertEquals(0, mockParent.getInvalidationCount()); + + builder.getBuilder().setOptionalInt32(10); + assertEquals(0, mockParent.getInvalidationCount()); + TestAllTypes message = builder.build(); + assertEquals(10, message.getOptionalInt32()); + + // Test that we receive invalidations now that build has been called. + assertEquals(0, mockParent.getInvalidationCount()); + builder.getBuilder().setOptionalInt32(20); + assertEquals(1, mockParent.getInvalidationCount()); + + // Test that we don't keep getting invalidations on every change + builder.getBuilder().setOptionalInt32(30); + assertEquals(1, mockParent.getInvalidationCount()); + + } + + public void testSetMessage() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + SingleFieldBuilder builder = + new SingleFieldBuilder( + TestAllTypes.getDefaultInstance(), + mockParent, + false); + builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); + assertEquals(0, builder.getMessage().getOptionalInt32()); + + // Update message using the builder + builder.getBuilder().setOptionalInt32(1); + assertEquals(0, mockParent.getInvalidationCount()); + assertEquals(1, builder.getBuilder().getOptionalInt32()); + assertEquals(1, builder.getMessage().getOptionalInt32()); + builder.build(); + builder.getBuilder().setOptionalInt32(2); + assertEquals(2, builder.getBuilder().getOptionalInt32()); + assertEquals(2, builder.getMessage().getOptionalInt32()); + + // Make sure message stays cached + assertSame(builder.getMessage(), builder.getMessage()); + } + + public void testClear() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + SingleFieldBuilder builder = + new SingleFieldBuilder( + TestAllTypes.getDefaultInstance(), + mockParent, + false); + builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); + assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); + builder.clear(); + assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); + + builder.getBuilder().setOptionalInt32(1); + assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); + builder.clear(); + assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); + } + + public void testMerge() { + TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); + SingleFieldBuilder builder = + new SingleFieldBuilder( + TestAllTypes.getDefaultInstance(), + mockParent, + false); + + // Merge into default field. + builder.mergeFrom(TestAllTypes.getDefaultInstance()); + assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); + + // Merge into non-default field on existing builder. + builder.getBuilder().setOptionalInt32(2); + builder.mergeFrom(TestAllTypes.newBuilder() + .setOptionalDouble(4.0) + .buildPartial()); + assertEquals(2, builder.getMessage().getOptionalInt32()); + assertEquals(4.0, builder.getMessage().getOptionalDouble()); + + // Merge into non-default field on existing message + builder.setMessage(TestAllTypes.newBuilder() + .setOptionalInt32(10) + .buildPartial()); + builder.mergeFrom(TestAllTypes.newBuilder() + .setOptionalDouble(5.0) + .buildPartial()); + assertEquals(10, builder.getMessage().getOptionalInt32()); + assertEquals(5.0, builder.getMessage().getOptionalDouble()); + } +} diff --git a/java/src/test/java/com/google/protobuf/SmallSortedMapTest.java b/java/src/test/java/com/google/protobuf/SmallSortedMapTest.java new file mode 100644 index 0000000..8f77a03 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/SmallSortedMapTest.java @@ -0,0 +1,420 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +/** + * @author darick@google.com Darick Tong + */ +public class SmallSortedMapTest extends TestCase { + // java.util.AbstractMap.SimpleEntry is private in JDK 1.5. We re-implement it + // here for JDK 1.5 users. + private static class SimpleEntry implements Map.Entry { + private final K key; + private V value; + + SimpleEntry(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V value) { + V oldValue = this.value; + this.value = value; + return oldValue; + } + + private static boolean eq(Object o1, Object o2) { + return o1 == null ? o2 == null : o1.equals(o2); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Map.Entry)) + return false; + Map.Entry e = (Map.Entry) o; + return eq(key, e.getKey()) && eq(value, e.getValue()); + } + + @Override + public int hashCode() { + return ((key == null) ? 0 : key.hashCode()) ^ + ((value == null) ? 0 : value.hashCode()); + } + } + + public void testPutAndGetArrayEntriesOnly() { + runPutAndGetTest(3); + } + + public void testPutAndGetOverflowEntries() { + runPutAndGetTest(6); + } + + private void runPutAndGetTest(int numElements) { + // Test with even and odd arraySize + SmallSortedMap map1 = + SmallSortedMap.newInstanceForTest(3); + SmallSortedMap map2 = + SmallSortedMap.newInstanceForTest(4); + SmallSortedMap map3 = + SmallSortedMap.newInstanceForTest(3); + SmallSortedMap map4 = + SmallSortedMap.newInstanceForTest(4); + + // Test with puts in ascending order. + for (int i = 0; i < numElements; i++) { + assertNull(map1.put(i, i + 1)); + assertNull(map2.put(i, i + 1)); + } + // Test with puts in descending order. + for (int i = numElements - 1; i >= 0; i--) { + assertNull(map3.put(i, i + 1)); + assertNull(map4.put(i, i + 1)); + } + + assertEquals(Math.min(3, numElements), map1.getNumArrayEntries()); + assertEquals(Math.min(4, numElements), map2.getNumArrayEntries()); + assertEquals(Math.min(3, numElements), map3.getNumArrayEntries()); + assertEquals(Math.min(4, numElements), map4.getNumArrayEntries()); + + List> allMaps = + new ArrayList>(); + allMaps.add(map1); + allMaps.add(map2); + allMaps.add(map3); + allMaps.add(map4); + + for (SmallSortedMap map : allMaps) { + assertEquals(numElements, map.size()); + for (int i = 0; i < numElements; i++) { + assertEquals(new Integer(i + 1), map.get(i)); + } + } + + assertEquals(map1, map2); + assertEquals(map2, map3); + assertEquals(map3, map4); + } + + public void testReplacingPut() { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + for (int i = 0; i < 6; i++) { + assertNull(map.put(i, i + 1)); + assertNull(map.remove(i + 1)); + } + for (int i = 0; i < 6; i++) { + assertEquals(new Integer(i + 1), map.put(i, i + 2)); + } + } + + public void testRemove() { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + for (int i = 0; i < 6; i++) { + assertNull(map.put(i, i + 1)); + assertNull(map.remove(i + 1)); + } + + assertEquals(3, map.getNumArrayEntries()); + assertEquals(3, map.getNumOverflowEntries()); + assertEquals(6, map.size()); + assertEquals(makeSortedKeySet(0, 1, 2, 3, 4, 5), map.keySet()); + + assertEquals(new Integer(2), map.remove(1)); + assertEquals(3, map.getNumArrayEntries()); + assertEquals(2, map.getNumOverflowEntries()); + assertEquals(5, map.size()); + assertEquals(makeSortedKeySet(0, 2, 3, 4, 5), map.keySet()); + + assertEquals(new Integer(5), map.remove(4)); + assertEquals(3, map.getNumArrayEntries()); + assertEquals(1, map.getNumOverflowEntries()); + assertEquals(4, map.size()); + assertEquals(makeSortedKeySet(0, 2, 3, 5), map.keySet()); + + assertEquals(new Integer(4), map.remove(3)); + assertEquals(3, map.getNumArrayEntries()); + assertEquals(0, map.getNumOverflowEntries()); + assertEquals(3, map.size()); + assertEquals(makeSortedKeySet(0, 2, 5), map.keySet()); + + assertNull(map.remove(3)); + assertEquals(3, map.getNumArrayEntries()); + assertEquals(0, map.getNumOverflowEntries()); + assertEquals(3, map.size()); + + assertEquals(new Integer(1), map.remove(0)); + assertEquals(2, map.getNumArrayEntries()); + assertEquals(0, map.getNumOverflowEntries()); + assertEquals(2, map.size()); + } + + public void testClear() { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + for (int i = 0; i < 6; i++) { + assertNull(map.put(i, i + 1)); + } + map.clear(); + assertEquals(0, map.getNumArrayEntries()); + assertEquals(0, map.getNumOverflowEntries()); + assertEquals(0, map.size()); + } + + public void testGetArrayEntryAndOverflowEntries() { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + for (int i = 0; i < 6; i++) { + assertNull(map.put(i, i + 1)); + } + assertEquals(3, map.getNumArrayEntries()); + for (int i = 0; i < 3; i++) { + Map.Entry entry = map.getArrayEntryAt(i); + assertEquals(new Integer(i), entry.getKey()); + assertEquals(new Integer(i + 1), entry.getValue()); + } + Iterator> it = + map.getOverflowEntries().iterator(); + for (int i = 3; i < 6; i++) { + assertTrue(it.hasNext()); + Map.Entry entry = it.next(); + assertEquals(new Integer(i), entry.getKey()); + assertEquals(new Integer(i + 1), entry.getValue()); + } + assertFalse(it.hasNext()); + } + + public void testEntrySetContains() { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + for (int i = 0; i < 6; i++) { + assertNull(map.put(i, i + 1)); + } + Set> entrySet = map.entrySet(); + for (int i = 0; i < 6; i++) { + assertTrue( + entrySet.contains(new SimpleEntry(i, i + 1))); + assertFalse( + entrySet.contains(new SimpleEntry(i, i))); + } + } + + public void testEntrySetAdd() { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + Set> entrySet = map.entrySet(); + for (int i = 0; i < 6; i++) { + Map.Entry entry = + new SimpleEntry(i, i + 1); + assertTrue(entrySet.add(entry)); + assertFalse(entrySet.add(entry)); + } + for (int i = 0; i < 6; i++) { + assertEquals(new Integer(i + 1), map.get(i)); + } + assertEquals(3, map.getNumArrayEntries()); + assertEquals(3, map.getNumOverflowEntries()); + assertEquals(6, map.size()); + } + + public void testEntrySetRemove() { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + Set> entrySet = map.entrySet(); + for (int i = 0; i < 6; i++) { + assertNull(map.put(i, i + 1)); + } + for (int i = 0; i < 6; i++) { + Map.Entry entry = + new SimpleEntry(i, i + 1); + assertTrue(entrySet.remove(entry)); + assertFalse(entrySet.remove(entry)); + } + assertTrue(map.isEmpty()); + assertEquals(0, map.getNumArrayEntries()); + assertEquals(0, map.getNumOverflowEntries()); + assertEquals(0, map.size()); + } + + public void testEntrySetClear() { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + for (int i = 0; i < 6; i++) { + assertNull(map.put(i, i + 1)); + } + map.entrySet().clear(); + assertTrue(map.isEmpty()); + assertEquals(0, map.getNumArrayEntries()); + assertEquals(0, map.getNumOverflowEntries()); + assertEquals(0, map.size()); + } + + public void testEntrySetIteratorNext() { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + for (int i = 0; i < 6; i++) { + assertNull(map.put(i, i + 1)); + } + Iterator> it = map.entrySet().iterator(); + for (int i = 0; i < 6; i++) { + assertTrue(it.hasNext()); + Map.Entry entry = it.next(); + assertEquals(new Integer(i), entry.getKey()); + assertEquals(new Integer(i + 1), entry.getValue()); + } + assertFalse(it.hasNext()); + } + + public void testEntrySetIteratorRemove() { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + for (int i = 0; i < 6; i++) { + assertNull(map.put(i, i + 1)); + } + Iterator> it = map.entrySet().iterator(); + for (int i = 0; i < 6; i++) { + assertTrue(map.containsKey(i)); + it.next(); + it.remove(); + assertFalse(map.containsKey(i)); + assertEquals(6 - i - 1, map.size()); + } + } + + public void testMapEntryModification() { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + for (int i = 0; i < 6; i++) { + assertNull(map.put(i, i + 1)); + } + Iterator> it = map.entrySet().iterator(); + for (int i = 0; i < 6; i++) { + Map.Entry entry = it.next(); + entry.setValue(i + 23); + } + for (int i = 0; i < 6; i++) { + assertEquals(new Integer(i + 23), map.get(i)); + } + } + + public void testMakeImmutable() { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + for (int i = 0; i < 6; i++) { + assertNull(map.put(i, i + 1)); + } + map.makeImmutable(); + assertEquals(new Integer(1), map.get(0)); + assertEquals(6, map.size()); + + try { + map.put(23, 23); + fail("Expected UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) { + } + + Map other = new HashMap(); + other.put(23, 23); + try { + map.putAll(other); + fail("Expected UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) { + } + + try { + map.remove(0); + fail("Expected UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) { + } + + try { + map.clear(); + fail("Expected UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) { + } + + Set> entrySet = map.entrySet(); + try { + entrySet.clear(); + fail("Expected UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) { + } + + Iterator> it = entrySet.iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + try { + entry.setValue(0); + fail("Expected UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) { + } + try { + it.remove(); + fail("Expected UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) { + } + } + + Set keySet = map.keySet(); + try { + keySet.clear(); + fail("Expected UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) { + } + + Iterator keys = keySet.iterator(); + while (keys.hasNext()) { + Integer key = keys.next(); + try { + keySet.remove(key); + fail("Expected UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) { + } + try { + keys.remove(); + fail("Expected UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) { + } + } + } + + private Set makeSortedKeySet(Integer... keys) { + return new TreeSet(Arrays.asList(keys)); + } +} diff --git a/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java new file mode 100644 index 0000000..84f1694 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java @@ -0,0 +1,96 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import junit.framework.TestCase; + +/** + * Tests that proto2 api generation doesn't cause compile errors when + * compiling protocol buffers that have names that would otherwise conflict + * if not fully qualified (like @Deprecated and @Override). + * + * @author jonp@google.com (Jon Perlow) + */ +public class TestBadIdentifiers extends TestCase { + + public void testCompilation() { + // If this compiles, it means the generation was correct. + TestBadIdentifiersProto.Deprecated.newBuilder(); + TestBadIdentifiersProto.Override.newBuilder(); + } + + public void testGetDescriptor() { + Descriptors.FileDescriptor fileDescriptor = + TestBadIdentifiersProto.getDescriptor(); + String descriptorField = TestBadIdentifiersProto.Descriptor + .getDefaultInstance().getDescriptor(); + Descriptors.Descriptor protoDescriptor = TestBadIdentifiersProto.Descriptor + .getDefaultInstance().getDescriptorForType(); + String nestedDescriptorField = TestBadIdentifiersProto.Descriptor + .NestedDescriptor.getDefaultInstance().getDescriptor(); + Descriptors.Descriptor nestedProtoDescriptor = TestBadIdentifiersProto + .Descriptor.NestedDescriptor.getDefaultInstance() + .getDescriptorForType(); + } + + public void testConflictingFieldNames() throws Exception { + TestBadIdentifiersProto.TestConflictingFieldNames message = + TestBadIdentifiersProto.TestConflictingFieldNames.getDefaultInstance(); + // Make sure generated accessors are properly named. + assertEquals(0, message.getInt32Field1Count()); + assertEquals(0, message.getEnumField2Count()); + assertEquals(0, message.getStringField3Count()); + assertEquals(0, message.getBytesField4Count()); + assertEquals(0, message.getMessageField5Count()); + + assertEquals(0, message.getInt32FieldCount11()); + assertEquals(1, message.getEnumFieldCount12().getNumber()); + assertEquals("", message.getStringFieldCount13()); + assertEquals(ByteString.EMPTY, message.getBytesFieldCount14()); + assertEquals(0, message.getMessageFieldCount15().getSerializedSize()); + + assertEquals(0, message.getInt32Field21Count()); + assertEquals(0, message.getEnumField22Count()); + assertEquals(0, message.getStringField23Count()); + assertEquals(0, message.getBytesField24Count()); + assertEquals(0, message.getMessageField25Count()); + + assertEquals(0, message.getInt32Field1List().size()); + assertEquals(0, message.getInt32FieldList31()); + + assertEquals(0, message.getInt64FieldCount()); + assertEquals(0L, message.getExtension( + TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldCount).longValue()); + assertEquals(0L, message.getExtension( + TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldList).longValue()); + + } +} diff --git a/java/src/test/java/com/google/protobuf/TestUtil.java b/java/src/test/java/com/google/protobuf/TestUtil.java index 2b8b2af..e3cf8a6 100644 --- a/java/src/test/java/com/google/protobuf/TestUtil.java +++ b/java/src/test/java/com/google/protobuf/TestUtil.java @@ -56,6 +56,11 @@ import static protobuf_unittest.UnittestProto.defaultImportEnumExtension; import static protobuf_unittest.UnittestProto.defaultStringPieceExtension; import static protobuf_unittest.UnittestProto.defaultCordExtension; +import static protobuf_unittest.UnittestProto.oneofUint32Extension; +import static protobuf_unittest.UnittestProto.oneofNestedMessageExtension; +import static protobuf_unittest.UnittestProto.oneofStringExtension; +import static protobuf_unittest.UnittestProto.oneofBytesExtension; + import static protobuf_unittest.UnittestProto.optionalInt32Extension; import static protobuf_unittest.UnittestProto.optionalInt64Extension; import static protobuf_unittest.UnittestProto.optionalUint32Extension; @@ -72,14 +77,16 @@ import static protobuf_unittest.UnittestProto.optionalBoolExtension; import static protobuf_unittest.UnittestProto.optionalStringExtension; import static protobuf_unittest.UnittestProto.optionalBytesExtension; import static protobuf_unittest.UnittestProto.optionalGroupExtension; -import static protobuf_unittest.UnittestProto.optionalNestedMessageExtension; +import static protobuf_unittest.UnittestProto.optionalCordExtension; +import static protobuf_unittest.UnittestProto.optionalForeignEnumExtension; import static protobuf_unittest.UnittestProto.optionalForeignMessageExtension; +import static protobuf_unittest.UnittestProto.optionalImportEnumExtension; import static protobuf_unittest.UnittestProto.optionalImportMessageExtension; import static protobuf_unittest.UnittestProto.optionalNestedEnumExtension; -import static protobuf_unittest.UnittestProto.optionalForeignEnumExtension; -import static protobuf_unittest.UnittestProto.optionalImportEnumExtension; +import static protobuf_unittest.UnittestProto.optionalNestedMessageExtension; +import static protobuf_unittest.UnittestProto.optionalPublicImportMessageExtension; +import static protobuf_unittest.UnittestProto.optionalLazyMessageExtension; import static protobuf_unittest.UnittestProto.optionalStringPieceExtension; -import static protobuf_unittest.UnittestProto.optionalCordExtension; import static protobuf_unittest.UnittestProto.repeatedInt32Extension; import static protobuf_unittest.UnittestProto.repeatedInt64Extension; @@ -100,6 +107,7 @@ import static protobuf_unittest.UnittestProto.repeatedGroupExtension; import static protobuf_unittest.UnittestProto.repeatedNestedMessageExtension; import static protobuf_unittest.UnittestProto.repeatedForeignMessageExtension; import static protobuf_unittest.UnittestProto.repeatedImportMessageExtension; +import static protobuf_unittest.UnittestProto.repeatedLazyMessageExtension; import static protobuf_unittest.UnittestProto.repeatedNestedEnumExtension; import static protobuf_unittest.UnittestProto.repeatedForeignEnumExtension; import static protobuf_unittest.UnittestProto.repeatedImportEnumExtension; @@ -145,6 +153,11 @@ import static com.google.protobuf.UnittestLite.defaultImportEnumExtensionLite; import static com.google.protobuf.UnittestLite.defaultStringPieceExtensionLite; import static com.google.protobuf.UnittestLite.defaultCordExtensionLite; +import static com.google.protobuf.UnittestLite.oneofUint32ExtensionLite; +import static com.google.protobuf.UnittestLite.oneofNestedMessageExtensionLite; +import static com.google.protobuf.UnittestLite.oneofStringExtensionLite; +import static com.google.protobuf.UnittestLite.oneofBytesExtensionLite; + import static com.google.protobuf.UnittestLite.optionalInt32ExtensionLite; import static com.google.protobuf.UnittestLite.optionalInt64ExtensionLite; import static com.google.protobuf.UnittestLite.optionalUint32ExtensionLite; @@ -162,11 +175,13 @@ import static com.google.protobuf.UnittestLite.optionalStringExtensionLite; import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite; import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite; import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite; +import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite; import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite; +import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite; import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite; import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite; -import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite; -import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite; +import static com.google.protobuf.UnittestLite.optionalPublicImportMessageExtensionLite; +import static com.google.protobuf.UnittestLite.optionalLazyMessageExtensionLite; import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite; import static com.google.protobuf.UnittestLite.optionalCordExtensionLite; @@ -189,6 +204,7 @@ import static com.google.protobuf.UnittestLite.repeatedGroupExtensionLite; import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite; import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite; import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedLazyMessageExtensionLite; import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite; import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite; import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite; @@ -214,22 +230,28 @@ import static com.google.protobuf.UnittestLite.packedBoolExtensionLite; import static com.google.protobuf.UnittestLite.packedEnumExtensionLite; import protobuf_unittest.UnittestProto.TestAllExtensions; +import protobuf_unittest.UnittestProto.TestAllExtensionsOrBuilder; import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder; +import protobuf_unittest.UnittestProto.TestOneof2; import protobuf_unittest.UnittestProto.TestPackedExtensions; import protobuf_unittest.UnittestProto.TestPackedTypes; import protobuf_unittest.UnittestProto.TestUnpackedTypes; import protobuf_unittest.UnittestProto.ForeignMessage; import protobuf_unittest.UnittestProto.ForeignEnum; -import com.google.protobuf.test.UnittestImport.ImportMessage; import com.google.protobuf.test.UnittestImport.ImportEnum; +import com.google.protobuf.test.UnittestImport.ImportMessage; +import com.google.protobuf.test.UnittestImportPublic.PublicImportMessage; import com.google.protobuf.UnittestLite.TestAllTypesLite; import com.google.protobuf.UnittestLite.TestAllExtensionsLite; +import com.google.protobuf.UnittestLite.TestAllExtensionsLiteOrBuilder; import com.google.protobuf.UnittestLite.TestPackedExtensionsLite; import com.google.protobuf.UnittestLite.ForeignMessageLite; import com.google.protobuf.UnittestLite.ForeignEnumLite; -import com.google.protobuf.UnittestImportLite.ImportMessageLite; import com.google.protobuf.UnittestImportLite.ImportEnumLite; +import com.google.protobuf.UnittestImportLite.ImportMessageLite; +import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite; import junit.framework.Assert; @@ -239,14 +261,17 @@ import java.io.RandomAccessFile; /** * Contains methods for setting all fields of {@code TestAllTypes} to - * some vaules as well as checking that all the fields are set to those values. + * some values as well as checking that all the fields are set to those values. * These are useful for testing various protocol message features, e.g. * set all fields of a message, serialize it, parse it, and check that all * fields are set. * + *

            This code is not to be used outside of {@code com.google.protobuf} and + * subpackages. + * * @author kenton@google.com Kenton Varda */ -class TestUtil { +public final class TestUtil { private TestUtil() {} /** Helper to convert a String to ByteString. */ @@ -269,6 +294,16 @@ class TestUtil { } /** + * Get a {@code TestAllTypes.Builder} with all fields set as they would be by + * {@link #setAllFields(TestAllTypes.Builder)}. + */ + public static TestAllTypes.Builder getAllSetBuilder() { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + setAllFields(builder); + return builder; + } + + /** * Get a {@code TestAllExtensions} with all fields set as they would be by * {@link #setAllExtensions(TestAllExtensions.Builder)}. */ @@ -338,6 +373,10 @@ class TestUtil { ForeignMessage.newBuilder().setC(119).build()); message.setOptionalImportMessage( ImportMessage.newBuilder().setD(120).build()); + message.setOptionalPublicImportMessage( + PublicImportMessage.newBuilder().setE(126).build()); + message.setOptionalLazyMessage( + TestAllTypes.NestedMessage.newBuilder().setBb(127).build()); message.setOptionalNestedEnum (TestAllTypes.NestedEnum.BAZ); message.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ); @@ -372,6 +411,8 @@ class TestUtil { ForeignMessage.newBuilder().setC(219).build()); message.addRepeatedImportMessage( ImportMessage.newBuilder().setD(220).build()); + message.addRepeatedLazyMessage( + TestAllTypes.NestedMessage.newBuilder().setBb(227).build()); message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAR); message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAR); @@ -405,6 +446,8 @@ class TestUtil { ForeignMessage.newBuilder().setC(319).build()); message.addRepeatedImportMessage( ImportMessage.newBuilder().setD(320).build()); + message.addRepeatedLazyMessage( + TestAllTypes.NestedMessage.newBuilder().setBb(327).build()); message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAZ); message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAZ); @@ -437,6 +480,12 @@ class TestUtil { message.setDefaultStringPiece("424"); message.setDefaultCord("425"); + + message.setOneofUint32(601); + message.setOneofNestedMessage( + TestAllTypes.NestedMessage.newBuilder().setBb(602).build()); + message.setOneofString("603"); + message.setOneofBytes(toBytes("604")); } // ------------------------------------------------------------------- @@ -470,6 +519,8 @@ class TestUtil { ForeignMessage.newBuilder().setC(519).build()); message.setRepeatedImportMessage(1, ImportMessage.newBuilder().setD(520).build()); + message.setRepeatedLazyMessage(1, + TestAllTypes.NestedMessage.newBuilder().setBb(527).build()); message.setRepeatedNestedEnum (1, TestAllTypes.NestedEnum.FOO); message.setRepeatedForeignEnum(1, ForeignEnum.FOREIGN_FOO); @@ -485,7 +536,7 @@ class TestUtil { * Assert (using {@code junit.framework.Assert}} that all fields of * {@code message} are set to the values assigned by {@code setAllFields}. */ - public static void assertAllFieldsSet(TestAllTypes message) { + public static void assertAllFieldsSet(TestAllTypesOrBuilder message) { Assert.assertTrue(message.hasOptionalInt32 ()); Assert.assertTrue(message.hasOptionalInt64 ()); Assert.assertTrue(message.hasOptionalUint32 ()); @@ -535,10 +586,12 @@ class TestUtil { Assert.assertEquals("115", message.getOptionalString ()); Assert.assertEquals(toBytes("116"), message.getOptionalBytes()); - Assert.assertEquals(117, message.getOptionalGroup ().getA()); - Assert.assertEquals(118, message.getOptionalNestedMessage ().getBb()); - Assert.assertEquals(119, message.getOptionalForeignMessage().getC()); - Assert.assertEquals(120, message.getOptionalImportMessage ().getD()); + Assert.assertEquals(117, message.getOptionalGroup ().getA()); + Assert.assertEquals(118, message.getOptionalNestedMessage ().getBb()); + Assert.assertEquals(119, message.getOptionalForeignMessage ().getC()); + Assert.assertEquals(120, message.getOptionalImportMessage ().getD()); + Assert.assertEquals(126, message.getOptionalPublicImportMessage().getE()); + Assert.assertEquals(127, message.getOptionalLazyMessage ().getBb()); Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getOptionalNestedEnum()); Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getOptionalForeignEnum()); @@ -569,6 +622,7 @@ class TestUtil { Assert.assertEquals(2, message.getRepeatedNestedMessageCount ()); Assert.assertEquals(2, message.getRepeatedForeignMessageCount()); Assert.assertEquals(2, message.getRepeatedImportMessageCount ()); + Assert.assertEquals(2, message.getRepeatedLazyMessageCount ()); Assert.assertEquals(2, message.getRepeatedNestedEnumCount ()); Assert.assertEquals(2, message.getRepeatedForeignEnumCount ()); Assert.assertEquals(2, message.getRepeatedImportEnumCount ()); @@ -596,6 +650,7 @@ class TestUtil { Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb()); Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC()); Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD()); + Assert.assertEquals(227, message.getRepeatedLazyMessage (0).getBb()); Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0)); Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0)); @@ -624,6 +679,7 @@ class TestUtil { Assert.assertEquals(318, message.getRepeatedNestedMessage (1).getBb()); Assert.assertEquals(319, message.getRepeatedForeignMessage(1).getC()); Assert.assertEquals(320, message.getRepeatedImportMessage (1).getD()); + Assert.assertEquals(327, message.getRepeatedLazyMessage (1).getBb()); Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnum (1)); Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getRepeatedForeignEnum(1)); @@ -679,16 +735,22 @@ class TestUtil { Assert.assertEquals("424", message.getDefaultStringPiece()); Assert.assertEquals("425", message.getDefaultCord()); + + Assert.assertFalse(message.hasOneofUint32()); + Assert.assertFalse(message.hasOneofNestedMessage()); + Assert.assertFalse(message.hasOneofString()); + Assert.assertTrue(message.hasOneofBytes()); + + Assert.assertEquals(toBytes("604"), message.getOneofBytes()); } // ------------------------------------------------------------------- - /** * Assert (using {@code junit.framework.Assert}} that all fields of * {@code message} are cleared, and that getting the fields returns their * default values. */ - public static void assertClear(TestAllTypes message) { + public static void assertClear(TestAllTypesOrBuilder message) { // hasBlah() should initially be false for all optional fields. Assert.assertFalse(message.hasOptionalInt32 ()); Assert.assertFalse(message.hasOptionalInt64 ()); @@ -736,15 +798,19 @@ class TestUtil { Assert.assertEquals(ByteString.EMPTY, message.getOptionalBytes()); // Embedded messages should also be clear. - Assert.assertFalse(message.getOptionalGroup ().hasA()); - Assert.assertFalse(message.getOptionalNestedMessage ().hasBb()); - Assert.assertFalse(message.getOptionalForeignMessage().hasC()); - Assert.assertFalse(message.getOptionalImportMessage ().hasD()); - - Assert.assertEquals(0, message.getOptionalGroup ().getA()); - Assert.assertEquals(0, message.getOptionalNestedMessage ().getBb()); - Assert.assertEquals(0, message.getOptionalForeignMessage().getC()); - Assert.assertEquals(0, message.getOptionalImportMessage ().getD()); + Assert.assertFalse(message.getOptionalGroup ().hasA()); + Assert.assertFalse(message.getOptionalNestedMessage ().hasBb()); + Assert.assertFalse(message.getOptionalForeignMessage ().hasC()); + Assert.assertFalse(message.getOptionalImportMessage ().hasD()); + Assert.assertFalse(message.getOptionalPublicImportMessage().hasE()); + Assert.assertFalse(message.getOptionalLazyMessage ().hasBb()); + + Assert.assertEquals(0, message.getOptionalGroup ().getA()); + Assert.assertEquals(0, message.getOptionalNestedMessage ().getBb()); + Assert.assertEquals(0, message.getOptionalForeignMessage ().getC()); + Assert.assertEquals(0, message.getOptionalImportMessage ().getD()); + Assert.assertEquals(0, message.getOptionalPublicImportMessage().getE()); + Assert.assertEquals(0, message.getOptionalLazyMessage ().getBb()); // Enums without defaults are set to the first value in the enum. Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum ()); @@ -775,6 +841,7 @@ class TestUtil { Assert.assertEquals(0, message.getRepeatedNestedMessageCount ()); Assert.assertEquals(0, message.getRepeatedForeignMessageCount()); Assert.assertEquals(0, message.getRepeatedImportMessageCount ()); + Assert.assertEquals(0, message.getRepeatedLazyMessageCount ()); Assert.assertEquals(0, message.getRepeatedNestedEnumCount ()); Assert.assertEquals(0, message.getRepeatedForeignEnumCount ()); Assert.assertEquals(0, message.getRepeatedImportEnumCount ()); @@ -829,6 +896,11 @@ class TestUtil { Assert.assertEquals("abc", message.getDefaultStringPiece()); Assert.assertEquals("123", message.getDefaultCord()); + + Assert.assertFalse(message.hasOneofUint32()); + Assert.assertFalse(message.hasOneofNestedMessage()); + Assert.assertFalse(message.hasOneofString()); + Assert.assertFalse(message.hasOneofBytes()); } // ------------------------------------------------------------------- @@ -838,7 +910,8 @@ class TestUtil { * {@code message} are set to the values assigned by {@code setAllFields} * followed by {@code modifyRepeatedFields}. */ - public static void assertRepeatedFieldsModified(TestAllTypes message) { + public static void assertRepeatedFieldsModified( + TestAllTypesOrBuilder message) { // ModifyRepeatedFields only sets the second repeated element of each // field. In addition to verifying this, we also verify that the first // element and size were *not* modified. @@ -862,6 +935,7 @@ class TestUtil { Assert.assertEquals(2, message.getRepeatedNestedMessageCount ()); Assert.assertEquals(2, message.getRepeatedForeignMessageCount()); Assert.assertEquals(2, message.getRepeatedImportMessageCount ()); + Assert.assertEquals(2, message.getRepeatedLazyMessageCount ()); Assert.assertEquals(2, message.getRepeatedNestedEnumCount ()); Assert.assertEquals(2, message.getRepeatedForeignEnumCount ()); Assert.assertEquals(2, message.getRepeatedImportEnumCount ()); @@ -889,6 +963,7 @@ class TestUtil { Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb()); Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC()); Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD()); + Assert.assertEquals(227, message.getRepeatedLazyMessage (0).getBb()); Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0)); Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0)); @@ -918,6 +993,7 @@ class TestUtil { Assert.assertEquals(518, message.getRepeatedNestedMessage (1).getBb()); Assert.assertEquals(519, message.getRepeatedForeignMessage(1).getC()); Assert.assertEquals(520, message.getRepeatedImportMessage (1).getD()); + Assert.assertEquals(527, message.getRepeatedLazyMessage (1).getBb()); Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnum (1)); Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getRepeatedForeignEnum(1)); @@ -1204,6 +1280,10 @@ class TestUtil { ForeignMessage.newBuilder().setC(119).build()); message.setExtension(optionalImportMessageExtension, ImportMessage.newBuilder().setD(120).build()); + message.setExtension(optionalPublicImportMessageExtension, + PublicImportMessage.newBuilder().setE(126).build()); + message.setExtension(optionalLazyMessageExtension, + TestAllTypes.NestedMessage.newBuilder().setBb(127).build()); message.setExtension(optionalNestedEnumExtension, TestAllTypes.NestedEnum.BAZ); message.setExtension(optionalForeignEnumExtension, ForeignEnum.FOREIGN_BAZ); @@ -1238,6 +1318,8 @@ class TestUtil { ForeignMessage.newBuilder().setC(219).build()); message.addExtension(repeatedImportMessageExtension, ImportMessage.newBuilder().setD(220).build()); + message.addExtension(repeatedLazyMessageExtension, + TestAllTypes.NestedMessage.newBuilder().setBb(227).build()); message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAR); message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAR); @@ -1271,6 +1353,8 @@ class TestUtil { ForeignMessage.newBuilder().setC(319).build()); message.addExtension(repeatedImportMessageExtension, ImportMessage.newBuilder().setD(320).build()); + message.addExtension(repeatedLazyMessageExtension, + TestAllTypes.NestedMessage.newBuilder().setBb(327).build()); message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAZ); message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAZ); @@ -1303,6 +1387,12 @@ class TestUtil { message.setExtension(defaultStringPieceExtension, "424"); message.setExtension(defaultCordExtension, "425"); + + message.setExtension(oneofUint32Extension, 601); + message.setExtension(oneofNestedMessageExtension, + TestAllTypes.NestedMessage.newBuilder().setBb(602).build()); + message.setExtension(oneofStringExtension, "603"); + message.setExtension(oneofBytesExtension, toBytes("604")); } // ------------------------------------------------------------------- @@ -1337,6 +1427,8 @@ class TestUtil { ForeignMessage.newBuilder().setC(519).build()); message.setExtension(repeatedImportMessageExtension, 1, ImportMessage.newBuilder().setD(520).build()); + message.setExtension(repeatedLazyMessageExtension, 1, + TestAllTypes.NestedMessage.newBuilder().setBb(527).build()); message.setExtension(repeatedNestedEnumExtension , 1, TestAllTypes.NestedEnum.FOO); message.setExtension(repeatedForeignEnumExtension, 1, ForeignEnum.FOREIGN_FOO); @@ -1352,7 +1444,8 @@ class TestUtil { * Assert (using {@code junit.framework.Assert}} that all extensions of * {@code message} are set to the values assigned by {@code setAllExtensions}. */ - public static void assertAllExtensionsSet(TestAllExtensions message) { + public static void assertAllExtensionsSet( + TestAllExtensionsOrBuilder message) { Assert.assertTrue(message.hasExtension(optionalInt32Extension )); Assert.assertTrue(message.hasExtension(optionalInt64Extension )); Assert.assertTrue(message.hasExtension(optionalUint32Extension )); @@ -1402,10 +1495,12 @@ class TestUtil { assertEqualsExactType("115", message.getExtension(optionalStringExtension )); assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtension)); - assertEqualsExactType(117, message.getExtension(optionalGroupExtension ).getA()); - assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension ).getBb()); - assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension).getC()); - assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension ).getD()); + assertEqualsExactType(117, message.getExtension(optionalGroupExtension ).getA()); + assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension ).getBb()); + assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension ).getC()); + assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension ).getD()); + assertEqualsExactType(126, message.getExtension(optionalPublicImportMessageExtension).getE()); + assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtension ).getBb()); assertEqualsExactType(TestAllTypes.NestedEnum.BAZ, message.getExtension(optionalNestedEnumExtension)); @@ -1439,6 +1534,7 @@ class TestUtil { Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension )); Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension)); Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension )); + Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension )); Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension )); Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension )); Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension )); @@ -1466,6 +1562,7 @@ class TestUtil { assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb()); assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC()); assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD()); + assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension , 0).getBb()); assertEqualsExactType(TestAllTypes.NestedEnum.BAR, message.getExtension(repeatedNestedEnumExtension, 0)); @@ -1497,6 +1594,7 @@ class TestUtil { assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtension , 1).getBb()); assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtension, 1).getC()); assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtension , 1).getD()); + assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtension , 1).getBb()); assertEqualsExactType(TestAllTypes.NestedEnum.BAZ, message.getExtension(repeatedNestedEnumExtension, 1)); @@ -1558,6 +1656,10 @@ class TestUtil { assertEqualsExactType("424", message.getExtension(defaultStringPieceExtension)); assertEqualsExactType("425", message.getExtension(defaultCordExtension)); + + Assert.assertTrue(message.hasExtension(oneofBytesExtension)); + + assertEqualsExactType(toBytes("604"), message.getExtension(oneofBytesExtension)); } // ------------------------------------------------------------------- @@ -1567,7 +1669,7 @@ class TestUtil { * {@code message} are cleared, and that getting the extensions returns their * default values. */ - public static void assertExtensionsClear(TestAllExtensions message) { + public static void assertExtensionsClear(TestAllExtensionsOrBuilder message) { // hasBlah() should initially be false for all optional fields. Assert.assertFalse(message.hasExtension(optionalInt32Extension )); Assert.assertFalse(message.hasExtension(optionalInt64Extension )); @@ -1657,6 +1759,7 @@ class TestUtil { Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtension )); Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtension)); Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtension )); + Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtension )); Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtension )); Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtension )); Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtension )); @@ -1685,6 +1788,7 @@ class TestUtil { Assert.assertEquals(0, message.getExtension(repeatedNestedMessageExtension ).size()); Assert.assertEquals(0, message.getExtension(repeatedForeignMessageExtension).size()); Assert.assertEquals(0, message.getExtension(repeatedImportMessageExtension ).size()); + Assert.assertEquals(0, message.getExtension(repeatedLazyMessageExtension ).size()); Assert.assertEquals(0, message.getExtension(repeatedNestedEnumExtension ).size()); Assert.assertEquals(0, message.getExtension(repeatedForeignEnumExtension ).size()); Assert.assertEquals(0, message.getExtension(repeatedImportEnumExtension ).size()); @@ -1742,6 +1846,11 @@ class TestUtil { assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtension)); assertEqualsExactType("123", message.getExtension(defaultCordExtension)); + + Assert.assertFalse(message.hasExtension(oneofUint32Extension)); + Assert.assertFalse(message.hasExtension(oneofNestedMessageExtension)); + Assert.assertFalse(message.hasExtension(oneofStringExtension)); + Assert.assertFalse(message.hasExtension(oneofBytesExtension)); } // ------------------------------------------------------------------- @@ -1752,7 +1861,7 @@ class TestUtil { * followed by {@code modifyRepeatedExtensions}. */ public static void assertRepeatedExtensionsModified( - TestAllExtensions message) { + TestAllExtensionsOrBuilder message) { // ModifyRepeatedFields only sets the second repeated element of each // field. In addition to verifying this, we also verify that the first // element and size were *not* modified. @@ -1776,6 +1885,7 @@ class TestUtil { Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension )); Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension)); Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension )); + Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension )); Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension )); Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension )); Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension )); @@ -1803,6 +1913,7 @@ class TestUtil { assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb()); assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC()); assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD()); + assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension , 0).getBb()); assertEqualsExactType(TestAllTypes.NestedEnum.BAR, message.getExtension(repeatedNestedEnumExtension, 0)); @@ -1835,6 +1946,7 @@ class TestUtil { assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtension , 1).getBb()); assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtension, 1).getC()); assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtension , 1).getD()); + assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtension , 1).getBb()); assertEqualsExactType(TestAllTypes.NestedEnum.FOO, message.getExtension(repeatedNestedEnumExtension, 1)); @@ -1958,6 +2070,10 @@ class TestUtil { ForeignMessageLite.newBuilder().setC(119).build()); message.setExtension(optionalImportMessageExtensionLite, ImportMessageLite.newBuilder().setD(120).build()); + message.setExtension(optionalPublicImportMessageExtensionLite, + PublicImportMessageLite.newBuilder().setE(126).build()); + message.setExtension(optionalLazyMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build()); message.setExtension(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ); message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); @@ -1992,6 +2108,8 @@ class TestUtil { ForeignMessageLite.newBuilder().setC(219).build()); message.addExtension(repeatedImportMessageExtensionLite, ImportMessageLite.newBuilder().setD(220).build()); + message.addExtension(repeatedLazyMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build()); message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR); message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR); @@ -2025,6 +2143,8 @@ class TestUtil { ForeignMessageLite.newBuilder().setC(319).build()); message.addExtension(repeatedImportMessageExtensionLite, ImportMessageLite.newBuilder().setD(320).build()); + message.addExtension(repeatedLazyMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build()); message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ); message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); @@ -2057,6 +2177,12 @@ class TestUtil { message.setExtension(defaultStringPieceExtensionLite, "424"); message.setExtension(defaultCordExtensionLite, "425"); + + message.setExtension(oneofUint32ExtensionLite, 601); + message.setExtension(oneofNestedMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build()); + message.setExtension(oneofStringExtensionLite, "603"); + message.setExtension(oneofBytesExtensionLite, toBytes("604")); } // ------------------------------------------------------------------- @@ -2091,6 +2217,8 @@ class TestUtil { ForeignMessageLite.newBuilder().setC(519).build()); message.setExtension(repeatedImportMessageExtensionLite, 1, ImportMessageLite.newBuilder().setD(520).build()); + message.setExtension(repeatedLazyMessageExtensionLite, 1, + TestAllTypesLite.NestedMessage.newBuilder().setBb(527).build()); message.setExtension(repeatedNestedEnumExtensionLite , 1, TestAllTypesLite.NestedEnum.FOO); message.setExtension(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO); @@ -2106,7 +2234,8 @@ class TestUtil { * Assert (using {@code junit.framework.Assert}} that all extensions of * {@code message} are set to the values assigned by {@code setAllExtensions}. */ - public static void assertAllExtensionsSet(TestAllExtensionsLite message) { + public static void assertAllExtensionsSet( + TestAllExtensionsLiteOrBuilder message) { Assert.assertTrue(message.hasExtension(optionalInt32ExtensionLite )); Assert.assertTrue(message.hasExtension(optionalInt64ExtensionLite )); Assert.assertTrue(message.hasExtension(optionalUint32ExtensionLite )); @@ -2160,6 +2289,9 @@ class TestUtil { assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtensionLite ).getBb()); assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtensionLite).getC()); assertEqualsExactType(120, message.getExtension(optionalImportMessageExtensionLite ).getD()); + assertEqualsExactType(126, message.getExtension( + optionalPublicImportMessageExtensionLite).getE()); + assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtensionLite).getBb()); assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ, message.getExtension(optionalNestedEnumExtensionLite)); @@ -2193,6 +2325,7 @@ class TestUtil { Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite )); Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite )); Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite )); Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite )); Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite )); @@ -2220,6 +2353,7 @@ class TestUtil { assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb()); assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC()); assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD()); + assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite ,0).getBb()); assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR, message.getExtension(repeatedNestedEnumExtensionLite, 0)); @@ -2251,6 +2385,7 @@ class TestUtil { assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb()); assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtensionLite,1).getC()); assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtensionLite ,1).getD()); + assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtensionLite ,1).getBb()); assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ, message.getExtension(repeatedNestedEnumExtensionLite, 1)); @@ -2312,6 +2447,10 @@ class TestUtil { assertEqualsExactType("424", message.getExtension(defaultStringPieceExtensionLite)); assertEqualsExactType("425", message.getExtension(defaultCordExtensionLite)); + + Assert.assertTrue(message.hasExtension(oneofBytesExtensionLite)); + + assertEqualsExactType(toBytes("604"), message.getExtension(oneofBytesExtensionLite)); } // ------------------------------------------------------------------- @@ -2321,7 +2460,8 @@ class TestUtil { * {@code message} are cleared, and that getting the extensions returns their * default values. */ - public static void assertExtensionsClear(TestAllExtensionsLite message) { + public static void assertExtensionsClear( + TestAllExtensionsLiteOrBuilder message) { // hasBlah() should initially be false for all optional fields. Assert.assertFalse(message.hasExtension(optionalInt32ExtensionLite )); Assert.assertFalse(message.hasExtension(optionalInt64ExtensionLite )); @@ -2339,10 +2479,12 @@ class TestUtil { Assert.assertFalse(message.hasExtension(optionalStringExtensionLite )); Assert.assertFalse(message.hasExtension(optionalBytesExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite)); - Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalPublicImportMessageExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalLazyMessageExtensionLite )); Assert.assertFalse(message.hasExtension(optionalNestedEnumExtensionLite )); Assert.assertFalse(message.hasExtension(optionalForeignEnumExtensionLite)); @@ -2369,15 +2511,20 @@ class TestUtil { assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtensionLite)); // Embedded messages should also be clear. - Assert.assertFalse(message.getExtension(optionalGroupExtensionLite ).hasA()); - Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite ).hasBb()); - Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite).hasC()); - Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite ).hasD()); + Assert.assertFalse(message.getExtension(optionalGroupExtensionLite ).hasA()); + Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite ).hasBb()); + Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite ).hasC()); + Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite ).hasD()); + Assert.assertFalse(message.getExtension(optionalPublicImportMessageExtensionLite).hasE()); + Assert.assertFalse(message.getExtension(optionalLazyMessageExtensionLite ).hasBb()); assertEqualsExactType(0, message.getExtension(optionalGroupExtensionLite ).getA()); assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtensionLite ).getBb()); assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtensionLite).getC()); assertEqualsExactType(0, message.getExtension(optionalImportMessageExtensionLite ).getD()); + assertEqualsExactType(0, message.getExtension( + optionalPublicImportMessageExtensionLite).getE()); + assertEqualsExactType(0, message.getExtension(optionalLazyMessageExtensionLite ).getBb()); // Enums without defaults are set to the first value in the enum. assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO, @@ -2411,6 +2558,7 @@ class TestUtil { Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtensionLite )); Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtensionLite)); Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtensionLite )); Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtensionLite )); Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtensionLite )); Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtensionLite )); @@ -2468,6 +2616,11 @@ class TestUtil { assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtensionLite)); assertEqualsExactType("123", message.getExtension(defaultCordExtensionLite)); + + Assert.assertFalse(message.hasExtension(oneofUint32ExtensionLite)); + Assert.assertFalse(message.hasExtension(oneofNestedMessageExtensionLite)); + Assert.assertFalse(message.hasExtension(oneofStringExtensionLite)); + Assert.assertFalse(message.hasExtension(oneofBytesExtensionLite)); } // ------------------------------------------------------------------- @@ -2478,7 +2631,7 @@ class TestUtil { * followed by {@code modifyRepeatedExtensions}. */ public static void assertRepeatedExtensionsModified( - TestAllExtensionsLite message) { + TestAllExtensionsLiteOrBuilder message) { // ModifyRepeatedFields only sets the second repeated element of each // field. In addition to verifying this, we also verify that the first // element and size were *not* modified. @@ -2502,6 +2655,7 @@ class TestUtil { Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite )); Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite )); Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite )); Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite )); Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite )); @@ -2529,6 +2683,7 @@ class TestUtil { assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb()); assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC()); assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD()); + assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite ,0).getBb()); assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR, message.getExtension(repeatedNestedEnumExtensionLite, 0)); @@ -2561,6 +2716,7 @@ class TestUtil { assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb()); assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtensionLite,1).getC()); assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtensionLite ,1).getD()); + assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtensionLite ,1).getBb()); assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO, message.getExtension(repeatedNestedEnumExtensionLite, 1)); @@ -2652,6 +2808,82 @@ class TestUtil { message.getExtension(packedEnumExtensionLite, 1)); } + // =================================================================== + // oneof + public static void setOneof(TestOneof2.Builder message) { + message.setFooLazyMessage( + TestOneof2.NestedMessage.newBuilder().setQuxInt(100).build()); + message.setBarString("101"); + message.setBazInt(102); + message.setBazString("103"); + } + + public static void assertOneofSet(TestOneof2 message) { + Assert.assertTrue(message.hasFooLazyMessage ()); + Assert.assertTrue(message.getFooLazyMessage().hasQuxInt()); + + Assert.assertTrue(message.hasBarString()); + Assert.assertTrue(message.hasBazInt ()); + Assert.assertTrue(message.hasBazString()); + + Assert.assertEquals(100 , message.getFooLazyMessage().getQuxInt()); + Assert.assertEquals("101", message.getBarString ()); + Assert.assertEquals(102 , message.getBazInt ()); + Assert.assertEquals("103", message.getBazString ()); + } + + public static void assertAtMostOneFieldSetOneof(TestOneof2 message) { + int count = 0; + if (message.hasFooInt()) { ++count; } + if (message.hasFooString()) { ++count; } + if (message.hasFooCord()) { ++count; } + if (message.hasFooStringPiece()) { ++count; } + if (message.hasFooBytes()) { ++count; } + if (message.hasFooEnum()) { ++count; } + if (message.hasFooMessage()) { ++count; } + if (message.hasFooGroup()) { ++count; } + if (message.hasFooLazyMessage()) { ++count; } + Assert.assertTrue(count <= 1); + + count = 0; + if (message.hasBarInt()) { ++count; } + if (message.hasBarString()) { ++count; } + if (message.hasBarCord()) { ++count; } + if (message.hasBarStringPiece()) { ++count; } + if (message.hasBarBytes()) { ++count; } + if (message.hasBarEnum()) { ++count; } + Assert.assertTrue(count <= 1); + + switch (message.getFooCase()) { + case FOO_INT: + Assert.assertTrue(message.hasFooInt()); + break; + case FOO_STRING: + Assert.assertTrue(message.hasFooString()); + break; + case FOO_CORD: + Assert.assertTrue(message.hasFooCord()); + break; + case FOO_BYTES: + Assert.assertTrue(message.hasFooBytes()); + break; + case FOO_ENUM: + Assert.assertTrue(message.hasFooEnum()); + break; + case FOO_MESSAGE: + Assert.assertTrue(message.hasFooMessage()); + break; + case FOOGROUP: + Assert.assertTrue(message.hasFooGroup()); + break; + case FOO_LAZY_MESSAGE: + Assert.assertTrue(message.hasFooLazyMessage()); + break; + case FOO_NOT_SET: + break; + } + } + // ================================================================= /** @@ -2665,18 +2897,21 @@ class TestUtil { private final Descriptors.FileDescriptor file; private final Descriptors.FileDescriptor importFile; + private final Descriptors.FileDescriptor publicImportFile; private final Descriptors.Descriptor optionalGroup; private final Descriptors.Descriptor repeatedGroup; private final Descriptors.Descriptor nestedMessage; private final Descriptors.Descriptor foreignMessage; private final Descriptors.Descriptor importMessage; + private final Descriptors.Descriptor publicImportMessage; private final Descriptors.FieldDescriptor groupA; private final Descriptors.FieldDescriptor repeatedGroupA; private final Descriptors.FieldDescriptor nestedB; private final Descriptors.FieldDescriptor foreignC; private final Descriptors.FieldDescriptor importD; + private final Descriptors.FieldDescriptor importE; private final Descriptors.EnumDescriptor nestedEnum; private final Descriptors.EnumDescriptor foreignEnum; @@ -2713,6 +2948,7 @@ class TestUtil { this.file = baseDescriptor.getFile(); Assert.assertEquals(1, file.getDependencies().size()); this.importFile = file.getDependencies().get(0); + this.publicImportFile = importFile.getDependencies().get(0); Descriptors.Descriptor testAllTypes; if (baseDescriptor.getName() == "TestAllTypes") { @@ -2739,6 +2975,8 @@ class TestUtil { this.nestedMessage = testAllTypes.findNestedTypeByName("NestedMessage"); this.foreignMessage = file.findMessageTypeByName("ForeignMessage"); this.importMessage = importFile.findMessageTypeByName("ImportMessage"); + this.publicImportMessage = publicImportFile.findMessageTypeByName( + "PublicImportMessage"); this.nestedEnum = testAllTypes.findEnumTypeByName("NestedEnum"); this.foreignEnum = file.findEnumTypeByName("ForeignEnum"); @@ -2756,6 +2994,7 @@ class TestUtil { this.nestedB = nestedMessage .findFieldByName("bb"); this.foreignC = foreignMessage.findFieldByName("c"); this.importD = importMessage .findFieldByName("d"); + this.importE = publicImportMessage.findFieldByName("e"); this.nestedFoo = nestedEnum.findValueByName("FOO"); this.nestedBar = nestedEnum.findValueByName("BAR"); this.nestedBaz = nestedEnum.findValueByName("BAZ"); @@ -2774,6 +3013,7 @@ class TestUtil { Assert.assertNotNull(nestedB ); Assert.assertNotNull(foreignC ); Assert.assertNotNull(importD ); + Assert.assertNotNull(importE ); Assert.assertNotNull(nestedFoo ); Assert.assertNotNull(nestedBar ); Assert.assertNotNull(nestedBaz ); @@ -2810,8 +3050,8 @@ class TestUtil { return parent.newBuilderForField(field); } else { ExtensionRegistry.ExtensionInfo extension = - extensionRegistry.findExtensionByNumber(field.getContainingType(), - field.getNumber()); + extensionRegistry.findImmutableExtensionByNumber( + field.getContainingType(), field.getNumber()); Assert.assertNotNull(extension); Assert.assertNotNull(extension.defaultInstance); return extension.defaultInstance.newBuilderForType(); @@ -2854,6 +3094,12 @@ class TestUtil { message.setField(f("optional_import_message"), newBuilderForField(message, f("optional_import_message")) .setField(importD, 120).build()); + message.setField(f("optional_public_import_message"), + newBuilderForField(message, f("optional_public_import_message")) + .setField(importE, 126).build()); + message.setField(f("optional_lazy_message"), + newBuilderForField(message, f("optional_lazy_message")) + .setField(nestedB, 127).build()); message.setField(f("optional_nested_enum" ), nestedBaz); message.setField(f("optional_foreign_enum"), foreignBaz); @@ -2892,6 +3138,9 @@ class TestUtil { message.addRepeatedField(f("repeated_import_message"), newBuilderForField(message, f("repeated_import_message")) .setField(importD, 220).build()); + message.addRepeatedField(f("repeated_lazy_message"), + newBuilderForField(message, f("repeated_lazy_message")) + .setField(nestedB, 227).build()); message.addRepeatedField(f("repeated_nested_enum" ), nestedBar); message.addRepeatedField(f("repeated_foreign_enum"), foreignBar); @@ -2929,6 +3178,9 @@ class TestUtil { message.addRepeatedField(f("repeated_import_message"), newBuilderForField(message, f("repeated_import_message")) .setField(importD, 320).build()); + message.addRepeatedField(f("repeated_lazy_message"), + newBuilderForField(message, f("repeated_lazy_message")) + .setField(nestedB, 327).build()); message.addRepeatedField(f("repeated_nested_enum" ), nestedBaz); message.addRepeatedField(f("repeated_foreign_enum"), foreignBaz); @@ -2961,6 +3213,13 @@ class TestUtil { message.setField(f("default_string_piece" ), "424"); message.setField(f("default_cord" ), "425"); + + message.setField(f("oneof_uint32" ), 601); + message.setField(f("oneof_nested_message"), + newBuilderForField(message, f("oneof_nested_message")) + .setField(nestedB, 602).build()); + message.setField(f("oneof_string" ), "603"); + message.setField(f("oneof_bytes" ), toBytes("604")); } // ------------------------------------------------------------------- @@ -2999,6 +3258,9 @@ class TestUtil { message.setRepeatedField(f("repeated_import_message"), 1, newBuilderForField(message, f("repeated_import_message")) .setField(importD, 520).build()); + message.setRepeatedField(f("repeated_lazy_message"), 1, + newBuilderForField(message, f("repeated_lazy_message")) + .setField(nestedB, 527).build()); message.setRepeatedField(f("repeated_nested_enum" ), 1, nestedFoo); message.setRepeatedField(f("repeated_foreign_enum"), 1, foreignFoo); @@ -3015,7 +3277,7 @@ class TestUtil { * {@code message} are set to the values assigned by {@code setAllFields}, * using the {@link Message} reflection interface. */ - public void assertAllFieldsSetViaReflection(Message message) { + public void assertAllFieldsSetViaReflection(MessageOrBuilder message) { Assert.assertTrue(message.hasField(f("optional_int32" ))); Assert.assertTrue(message.hasField(f("optional_int64" ))); Assert.assertTrue(message.hasField(f("optional_uint32" ))); @@ -3083,6 +3345,12 @@ class TestUtil { Assert.assertEquals(120, ((Message)message.getField(f("optional_import_message"))) .getField(importD)); + Assert.assertEquals(126, + ((Message)message.getField(f("optional_public_import_message"))) + .getField(importE)); + Assert.assertEquals(127, + ((Message)message.getField(f("optional_lazy_message"))) + .getField(nestedB)); Assert.assertEquals( nestedBaz, message.getField(f("optional_nested_enum" ))); Assert.assertEquals(foreignBaz, message.getField(f("optional_foreign_enum"))); @@ -3113,6 +3381,7 @@ class TestUtil { Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" ))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" ))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" ))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum" ))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum" ))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum" ))); @@ -3148,6 +3417,9 @@ class TestUtil { Assert.assertEquals(220, ((Message)message.getRepeatedField(f("repeated_import_message"), 0)) .getField(importD)); + Assert.assertEquals(227, + ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0)) + .getField(nestedB)); Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0)); Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0)); @@ -3184,6 +3456,9 @@ class TestUtil { Assert.assertEquals(320, ((Message)message.getRepeatedField(f("repeated_import_message"), 1)) .getField(importD)); + Assert.assertEquals(327, + ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1)) + .getField(nestedB)); Assert.assertEquals( nestedBaz, message.getRepeatedField(f("repeated_nested_enum" ),1)); Assert.assertEquals(foreignBaz, message.getRepeatedField(f("repeated_foreign_enum"),1)); @@ -3239,6 +3514,24 @@ class TestUtil { Assert.assertEquals("424", message.getField(f("default_string_piece"))); Assert.assertEquals("425", message.getField(f("default_cord"))); + + Assert.assertTrue(message.hasField(f("oneof_bytes"))); + Assert.assertEquals(toBytes("604"), message.getField(f("oneof_bytes"))); + + if (extensionRegistry == null) { + Assert.assertFalse(message.hasField(f("oneof_uint32"))); + Assert.assertFalse(message.hasField(f("oneof_nested_message"))); + Assert.assertFalse(message.hasField(f("oneof_string"))); + } else { + Assert.assertTrue(message.hasField(f("oneof_uint32"))); + Assert.assertTrue(message.hasField(f("oneof_nested_message"))); + Assert.assertTrue(message.hasField(f("oneof_string"))); + Assert.assertEquals(601, message.getField(f("oneof_uint32"))); + Assert.assertEquals(602, + ((MessageOrBuilder) message.getField(f("oneof_nested_message"))) + .getField(nestedB)); + Assert.assertEquals("603", message.getField(f("oneof_string"))); + } } // ------------------------------------------------------------------- @@ -3248,7 +3541,7 @@ class TestUtil { * {@code message} are cleared, and that getting the fields returns their * default values, using the {@link Message} reflection interface. */ - public void assertClearViaReflection(Message message) { + public void assertClearViaReflection(MessageOrBuilder message) { // has_blah() should initially be false for all optional fields. Assert.assertFalse(message.hasField(f("optional_int32" ))); Assert.assertFalse(message.hasField(f("optional_int64" ))); @@ -3307,6 +3600,12 @@ class TestUtil { Assert.assertFalse( ((Message)message.getField(f("optional_import_message"))) .hasField(importD)); + Assert.assertFalse( + ((Message)message.getField(f("optional_public_import_message"))) + .hasField(importE)); + Assert.assertFalse( + ((Message)message.getField(f("optional_lazy_message"))) + .hasField(nestedB)); Assert.assertEquals(0, ((Message)message.getField(f("optionalgroup"))).getField(groupA)); @@ -3319,6 +3618,12 @@ class TestUtil { Assert.assertEquals(0, ((Message)message.getField(f("optional_import_message"))) .getField(importD)); + Assert.assertEquals(0, + ((Message)message.getField(f("optional_public_import_message"))) + .getField(importE)); + Assert.assertEquals(0, + ((Message)message.getField(f("optional_lazy_message"))) + .getField(nestedB)); // Enums without defaults are set to the first value in the enum. Assert.assertEquals( nestedFoo, message.getField(f("optional_nested_enum" ))); @@ -3349,6 +3654,7 @@ class TestUtil { Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_message" ))); Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_message"))); Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_message" ))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_lazy_message" ))); Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_enum" ))); Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_enum" ))); Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_enum" ))); @@ -3403,11 +3709,22 @@ class TestUtil { Assert.assertEquals("abc", message.getField(f("default_string_piece"))); Assert.assertEquals("123", message.getField(f("default_cord"))); + + Assert.assertFalse(message.hasField(f("oneof_uint32"))); + Assert.assertFalse(message.hasField(f("oneof_nested_message"))); + Assert.assertFalse(message.hasField(f("oneof_string"))); + Assert.assertFalse(message.hasField(f("oneof_bytes"))); + + Assert.assertEquals(0, message.getField(f("oneof_uint32"))); + Assert.assertEquals("", message.getField(f("oneof_string"))); + Assert.assertEquals(toBytes(""), message.getField(f("oneof_bytes"))); } + // --------------------------------------------------------------- - public void assertRepeatedFieldsModifiedViaReflection(Message message) { + public void assertRepeatedFieldsModifiedViaReflection( + MessageOrBuilder message) { // ModifyRepeatedFields only sets the second repeated element of each // field. In addition to verifying this, we also verify that the first // element and size were *not* modified. @@ -3431,6 +3748,7 @@ class TestUtil { Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" ))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" ))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" ))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum" ))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum" ))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum" ))); @@ -3466,6 +3784,9 @@ class TestUtil { Assert.assertEquals(220, ((Message)message.getRepeatedField(f("repeated_import_message"), 0)) .getField(importD)); + Assert.assertEquals(227, + ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0)) + .getField(nestedB)); Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0)); Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0)); @@ -3502,6 +3823,9 @@ class TestUtil { Assert.assertEquals(520, ((Message)message.getRepeatedField(f("repeated_import_message"), 1)) .getField(importD)); + Assert.assertEquals(527, + ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1)) + .getField(nestedB)); Assert.assertEquals( nestedFoo, message.getRepeatedField(f("repeated_nested_enum" ),1)); Assert.assertEquals(foreignFoo, message.getRepeatedField(f("repeated_foreign_enum"),1)); @@ -3543,7 +3867,7 @@ class TestUtil { message.addRepeatedField(f("packed_enum" ), foreignBaz); } - public void assertPackedFieldsSetViaReflection(Message message) { + public void assertPackedFieldsSetViaReflection(MessageOrBuilder message) { Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int32" ))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int64" ))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint32" ))); @@ -3699,7 +4023,7 @@ class TestUtil { /** * @param filePath The path relative to - * {@link com.google.testing.util.TestUtil#getDefaultSrcDir}. + * {@link #getTestDataDir}. */ public static String readTextFromFile(String filePath) { return readBytesFromFile(filePath).toStringUtf8(); @@ -3728,8 +4052,8 @@ class TestUtil { } /** - * @param filePath The path relative to - * {@link com.google.testing.util.TestUtil#getDefaultSrcDir}. + * @param filename The path relative to + * {@link #getTestDataDir}. */ public static ByteString readBytesFromFile(String filename) { File fullPath = new File(getTestDataDir(), filename); @@ -3749,13 +4073,13 @@ class TestUtil { /** * Get the bytes of the "golden message". This is a serialized TestAllTypes * with all fields set as they would be by - * {@link setAllFields(TestAllTypes.Builder)}, but it is loaded from a file + * {@link #setAllFields(TestAllTypes.Builder)}, but it is loaded from a file * on disk rather than generated dynamically. The file is actually generated * by C++ code, so testing against it verifies compatibility with C++. */ public static ByteString getGoldenMessage() { if (goldenMessage == null) { - goldenMessage = readBytesFromFile("golden_message"); + goldenMessage = readBytesFromFile("golden_message_oneof_implemented"); } return goldenMessage; } @@ -3764,7 +4088,7 @@ class TestUtil { /** * Get the bytes of the "golden packed fields message". This is a serialized * TestPackedTypes with all fields set as they would be by - * {@link setPackedFields(TestPackedTypes.Builder)}, but it is loaded from a + * {@link #setPackedFields(TestPackedTypes.Builder)}, but it is loaded from a * file on disk rather than generated dynamically. The file is actually * generated by C++ code, so testing against it verifies compatibility with * C++. @@ -3777,4 +4101,24 @@ class TestUtil { return goldenPackedFieldsMessage; } private static ByteString goldenPackedFieldsMessage = null; + + /** + * Mock implementation of {@link GeneratedMessage.BuilderParent} for testing. + * + * @author jonp@google.com (Jon Perlow) + */ + public static class MockBuilderParent + implements GeneratedMessage.BuilderParent { + + private int invalidations; + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public void markDirty() { + invalidations++; + } + + public int getInvalidationCount() { + return invalidations; + } + } } diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java index 60bd800..5b77569 100644 --- a/java/src/test/java/com/google/protobuf/TextFormatTest.java +++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java @@ -31,14 +31,16 @@ package com.google.protobuf; import com.google.protobuf.Descriptors.FieldDescriptor; -import protobuf_unittest.UnittestProto.OneString; -import protobuf_unittest.UnittestProto.TestAllTypes; -import protobuf_unittest.UnittestProto.TestAllExtensions; -import protobuf_unittest.UnittestProto.TestEmptyMessage; -import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage; +import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy; import protobuf_unittest.UnittestMset.TestMessageSet; import protobuf_unittest.UnittestMset.TestMessageSetExtension1; import protobuf_unittest.UnittestMset.TestMessageSetExtension2; +import protobuf_unittest.UnittestProto.OneString; +import protobuf_unittest.UnittestProto.TestAllExtensions; +import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage; +import protobuf_unittest.UnittestProto.TestEmptyMessage; +import protobuf_unittest.UnittestProto.TestOneof2; import junit.framework.TestCase; @@ -60,11 +62,11 @@ public class TextFormatTest extends TestCase { // A representation of the above string with all the characters escaped. private final static String kEscapeTestStringEscaped = - "\"\\\"A string with \\' characters \\n and \\r newlines " - + "and \\t tabs and \\001 slashes \\\\\""; + "\\\"A string with \\' characters \\n and \\r newlines " + + "and \\t tabs and \\001 slashes \\\\"; private static String allFieldsSetText = TestUtil.readTextFromFile( - "text_format_unittest_data.txt"); + "text_format_unittest_data_oneof_implemented.txt"); private static String allExtensionsSetText = TestUtil.readTextFromFile( "text_format_unittest_extensions_data.txt"); @@ -109,6 +111,23 @@ public class TextFormatTest extends TestCase { " str: \"foo\"\n" + "}\n"; + private String messageSetTextWithRepeatedExtension = + "[protobuf_unittest.TestMessageSetExtension1] {\n" + + " i: 123\n" + + "}\n" + + "[protobuf_unittest.TestMessageSetExtension1] {\n" + + " i: 456\n" + + "}\n"; + + private final TextFormat.Parser parserWithOverwriteForbidden = + TextFormat.Parser.newBuilder() + .setSingularOverwritePolicy( + SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES) + .build(); + + private final TextFormat.Parser defaultParser = + TextFormat.Parser.newBuilder().build(); + /** Print TestAllTypes and compare with golden file. */ public void testPrintMessage() throws Exception { String javaText = TextFormat.printToString(TestUtil.getAllSet()); @@ -121,6 +140,18 @@ public class TextFormatTest extends TestCase { assertEquals(allFieldsSetText, javaText); } + /** Print TestAllTypes as Builder and compare with golden file. */ + public void testPrintMessageBuilder() throws Exception { + String javaText = TextFormat.printToString(TestUtil.getAllSetBuilder()); + + // Java likes to add a trailing ".0" to floats and doubles. C printf + // (with %g format) does not. Our golden files are used for both + // C++ and Java TextFormat classes, so we need to conform. + javaText = javaText.replace(".0\n", "\n"); + + assertEquals(allFieldsSetText, javaText); + } + /** Print TestAllExtensions and compare with golden file. */ public void testPrintExtensions() throws Exception { String javaText = TextFormat.printToString(TestUtil.getAllExtensionsSet()); @@ -133,40 +164,44 @@ public class TextFormatTest extends TestCase { assertEquals(allExtensionsSetText, javaText); } + // Creates an example unknown field set. + private UnknownFieldSet makeUnknownFieldSet() { + return UnknownFieldSet.newBuilder() + .addField(5, + UnknownFieldSet.Field.newBuilder() + .addVarint(1) + .addFixed32(2) + .addFixed64(3) + .addLengthDelimited(ByteString.copyFromUtf8("4")) + .addGroup( + UnknownFieldSet.newBuilder() + .addField(10, + UnknownFieldSet.Field.newBuilder() + .addVarint(5) + .build()) + .build()) + .build()) + .addField(8, + UnknownFieldSet.Field.newBuilder() + .addVarint(1) + .addVarint(2) + .addVarint(3) + .build()) + .addField(15, + UnknownFieldSet.Field.newBuilder() + .addVarint(0xABCDEF1234567890L) + .addFixed32(0xABCD1234) + .addFixed64(0xABCDEF1234567890L) + .build()) + .build(); + } + public void testPrintUnknownFields() throws Exception { // Test printing of unknown fields in a message. TestEmptyMessage message = TestEmptyMessage.newBuilder() - .setUnknownFields( - UnknownFieldSet.newBuilder() - .addField(5, - UnknownFieldSet.Field.newBuilder() - .addVarint(1) - .addFixed32(2) - .addFixed64(3) - .addLengthDelimited(ByteString.copyFromUtf8("4")) - .addGroup( - UnknownFieldSet.newBuilder() - .addField(10, - UnknownFieldSet.Field.newBuilder() - .addVarint(5) - .build()) - .build()) - .build()) - .addField(8, - UnknownFieldSet.Field.newBuilder() - .addVarint(1) - .addVarint(2) - .addVarint(3) - .build()) - .addField(15, - UnknownFieldSet.Field.newBuilder() - .addVarint(0xABCDEF1234567890L) - .addFixed32(0xABCD1234) - .addFixed64(0xABCDEF1234567890L) - .build()) - .build()) + .setUnknownFields(makeUnknownFieldSet()) .build(); assertEquals( @@ -234,8 +269,8 @@ public class TextFormatTest extends TestCase { .addRepeatedInt32 (1 << 31) .addRepeatedUint32(1 << 31) - .addRepeatedInt64 (1l << 63) - .addRepeatedUint64(1l << 63) + .addRepeatedInt64 (1L << 63) + .addRepeatedUint64(1L << 63) // Floats of various precisions and exponents. .addRepeatedDouble(123) @@ -355,6 +390,40 @@ public class TextFormatTest extends TestCase { TestMessageSetExtension2.messageSetExtension)); assertEquals("foo", messageSet.getExtension( TestMessageSetExtension2.messageSetExtension).getStr()); + + builder = TestMessageSet.newBuilder(); + TextFormat.merge(messageSetTextWithRepeatedExtension, extensionRegistry, + builder); + messageSet = builder.build(); + assertEquals(456, messageSet.getExtension( + TestMessageSetExtension1.messageSetExtension).getI()); + } + + public void testParseMessageSetWithOverwriteForbidden() throws Exception { + ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); + extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); + extensionRegistry.add(TestMessageSetExtension2.messageSetExtension); + + TestMessageSet.Builder builder = TestMessageSet.newBuilder(); + parserWithOverwriteForbidden.merge( + messageSetText, extensionRegistry, builder); + TestMessageSet messageSet = builder.build(); + assertEquals(123, messageSet.getExtension( + TestMessageSetExtension1.messageSetExtension).getI()); + assertEquals("foo", messageSet.getExtension( + TestMessageSetExtension2.messageSetExtension).getStr()); + + builder = TestMessageSet.newBuilder(); + try { + parserWithOverwriteForbidden.merge( + messageSetTextWithRepeatedExtension, extensionRegistry, builder); + fail("expected parse exception"); + } catch (TextFormat.ParseException e) { + assertEquals("6:1: Non-repeated field " + + "\"protobuf_unittest.TestMessageSetExtension1.message_set_extension\"" + + " cannot be overwritten.", + e.getMessage()); + } } public void testParseNumericEnum() throws Exception { @@ -391,12 +460,32 @@ public class TextFormatTest extends TestCase { } } + private void assertParseErrorWithOverwriteForbidden(String error, + String text) { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + try { + parserWithOverwriteForbidden.merge( + text, TestUtil.getExtensionRegistry(), builder); + fail("Expected parse exception."); + } catch (TextFormat.ParseException e) { + assertEquals(error, e.getMessage()); + } + } + + private TestAllTypes assertParseSuccessWithOverwriteForbidden( + String text) throws TextFormat.ParseException { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + parserWithOverwriteForbidden.merge( + text, TestUtil.getExtensionRegistry(), builder); + return builder.build(); + } + public void testParseErrors() throws Exception { assertParseError( "1:16: Expected \":\".", "optional_int32 123"); assertParseError( - "1:23: Expected identifier.", + "1:23: Expected identifier. Found '?'", "optional_nested_enum: ?"); assertParseError( "1:18: Couldn't parse integer: Number must be positive: -1", @@ -409,6 +498,9 @@ public class TextFormatTest extends TestCase { "1:16: Expected \"true\" or \"false\".", "optional_bool: maybe"); assertParseError( + "1:16: Expected \"true\" or \"false\".", + "optional_bool: 2"); + assertParseError( "1:18: Expected string.", "optional_string: 123"); assertParseError( @@ -450,10 +542,10 @@ public class TextFormatTest extends TestCase { // Delimiters must match. assertParseError( - "1:22: Expected identifier.", + "1:22: Expected identifier. Found '}'", "OptionalGroup < a: 1 }"); assertParseError( - "1:22: Expected identifier.", + "1:22: Expected identifier. Found '>'", "OptionalGroup { a: 1 >"); } @@ -469,6 +561,10 @@ public class TextFormatTest extends TestCase { TextFormat.unescapeBytes("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"")); assertEquals("\0\001\007\b\f\n\r\t\013\\\'\"", TextFormat.unescapeText("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"")); + assertEquals(kEscapeTestStringEscaped, + TextFormat.escapeText(kEscapeTestString)); + assertEquals(kEscapeTestString, + TextFormat.unescapeText(kEscapeTestStringEscaped)); // Unicode handling. assertEquals("\\341\\210\\264", TextFormat.escapeText("\u1234")); @@ -481,6 +577,11 @@ public class TextFormatTest extends TestCase { assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\xe1\\x88\\xb4")); + // Handling of strings with unescaped Unicode characters > 255. + final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c"; + ByteString zhByteString = ByteString.copyFromUtf8(zh); + assertEquals(zhByteString, TextFormat.unescapeBytes(zh)); + // Errors. try { TextFormat.unescapeText("\\x"); @@ -622,6 +723,13 @@ public class TextFormatTest extends TestCase { } } + public void testParseString() throws Exception { + final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c"; + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + TextFormat.merge("optional_string: \"" + zh + "\"", builder); + assertEquals(zh, builder.getOptionalString()); + } + public void testParseLongString() throws Exception { String longText = "123456789012345678901234567890123456789012345678901234567890" + @@ -650,9 +758,237 @@ public class TextFormatTest extends TestCase { assertEquals(longText, builder.getOptionalString()); } + public void testParseBoolean() throws Exception { + String goodText = + "repeated_bool: t repeated_bool : 0\n" + + "repeated_bool :f repeated_bool:1"; + String goodTextCanonical = + "repeated_bool: true\n" + + "repeated_bool: false\n" + + "repeated_bool: false\n" + + "repeated_bool: true\n"; + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + TextFormat.merge(goodText, builder); + assertEquals(goodTextCanonical, builder.build().toString()); + + try { + TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder(); + TextFormat.merge("optional_bool:2", badBuilder); + fail("Should have thrown an exception."); + } catch (TextFormat.ParseException e) { + // success + } + try { + TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder(); + TextFormat.merge("optional_bool: foo", badBuilder); + fail("Should have thrown an exception."); + } catch (TextFormat.ParseException e) { + // success + } + } + public void testParseAdjacentStringLiterals() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TextFormat.merge("optional_string: \"foo\" 'corge' \"grault\"", builder); assertEquals("foocorgegrault", builder.getOptionalString()); } + + public void testPrintFieldValue() throws Exception { + assertPrintFieldValue("\"Hello\"", "Hello", "repeated_string"); + assertPrintFieldValue("123.0", 123f, "repeated_float"); + assertPrintFieldValue("123.0", 123d, "repeated_double"); + assertPrintFieldValue("123", 123, "repeated_int32"); + assertPrintFieldValue("123", 123L, "repeated_int64"); + assertPrintFieldValue("true", true, "repeated_bool"); + assertPrintFieldValue("4294967295", 0xFFFFFFFF, "repeated_uint32"); + assertPrintFieldValue("18446744073709551615", 0xFFFFFFFFFFFFFFFFL, + "repeated_uint64"); + assertPrintFieldValue("\"\\001\\002\\003\"", + ByteString.copyFrom(new byte[] {1, 2, 3}), "repeated_bytes"); + } + + private void assertPrintFieldValue(String expect, Object value, + String fieldName) throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + StringBuilder sb = new StringBuilder(); + TextFormat.printFieldValue( + TestAllTypes.getDescriptor().findFieldByName(fieldName), + value, sb); + assertEquals(expect, sb.toString()); + } + + public void testShortDebugString() { + assertEquals("optional_nested_message { bb: 42 } repeated_int32: 1" + + " repeated_uint32: 2", + TextFormat.shortDebugString(TestAllTypes.newBuilder() + .addRepeatedInt32(1) + .addRepeatedUint32(2) + .setOptionalNestedMessage( + NestedMessage.newBuilder().setBb(42).build()) + .build())); + } + + public void testShortDebugString_unknown() { + assertEquals("5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5 { 10: 5 }" + + " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:" + + " 0xabcdef1234567890", + TextFormat.shortDebugString(makeUnknownFieldSet())); + } + + public void testPrintToUnicodeString() throws Exception { + assertEquals( + "optional_string: \"abc\u3042efg\"\n" + + "optional_bytes: \"\\343\\201\\202\"\n" + + "repeated_string: \"\u3093XYZ\"\n", + TextFormat.printToUnicodeString(TestAllTypes.newBuilder() + .setOptionalString("abc\u3042efg") + .setOptionalBytes(bytes(0xe3, 0x81, 0x82)) + .addRepeatedString("\u3093XYZ") + .build())); + + // Double quotes and backslashes should be escaped + assertEquals( + "optional_string: \"a\\\\bc\\\"ef\\\"g\"\n", + TextFormat.printToUnicodeString(TestAllTypes.newBuilder() + .setOptionalString("a\\bc\"ef\"g") + .build())); + + // Test escaping roundtrip + TestAllTypes message = TestAllTypes.newBuilder() + .setOptionalString("a\\bc\\\"ef\"g") + .build(); + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + TextFormat.merge(TextFormat.printToUnicodeString(message), builder); + assertEquals(message.getOptionalString(), builder.getOptionalString()); + } + + public void testPrintToUnicodeStringWithNewlines() { + // No newlines at start and end + assertEquals("optional_string: \"test newlines\n\nin\nstring\"\n", + TextFormat.printToUnicodeString(TestAllTypes.newBuilder() + .setOptionalString("test newlines\n\nin\nstring") + .build())); + + // Newlines at start and end + assertEquals("optional_string: \"\ntest\nnewlines\n\nin\nstring\n\"\n", + TextFormat.printToUnicodeString(TestAllTypes.newBuilder() + .setOptionalString("\ntest\nnewlines\n\nin\nstring\n") + .build())); + + // Strings with 0, 1 and 2 newlines. + assertEquals("optional_string: \"\"\n", + TextFormat.printToUnicodeString(TestAllTypes.newBuilder() + .setOptionalString("") + .build())); + assertEquals("optional_string: \"\n\"\n", + TextFormat.printToUnicodeString(TestAllTypes.newBuilder() + .setOptionalString("\n") + .build())); + assertEquals("optional_string: \"\n\n\"\n", + TextFormat.printToUnicodeString(TestAllTypes.newBuilder() + .setOptionalString("\n\n") + .build())); + } + + public void testPrintToUnicodeString_unknown() { + assertEquals( + "1: \"\\343\\201\\202\"\n", + TextFormat.printToUnicodeString(UnknownFieldSet.newBuilder() + .addField(1, + UnknownFieldSet.Field.newBuilder() + .addLengthDelimited(bytes(0xe3, 0x81, 0x82)).build()) + .build())); + } + + public void testParseNonRepeatedFields() throws Exception { + assertParseSuccessWithOverwriteForbidden( + "repeated_int32: 1\n" + + "repeated_int32: 2\n"); + assertParseSuccessWithOverwriteForbidden( + "RepeatedGroup { a: 1 }\n" + + "RepeatedGroup { a: 2 }\n"); + assertParseSuccessWithOverwriteForbidden( + "repeated_nested_message { bb: 1 }\n" + + "repeated_nested_message { bb: 2 }\n"); + assertParseErrorWithOverwriteForbidden( + "3:17: Non-repeated field " + + "\"protobuf_unittest.TestAllTypes.optional_int32\" " + + "cannot be overwritten.", + "optional_int32: 1\n" + + "optional_bool: true\n" + + "optional_int32: 1\n"); + assertParseErrorWithOverwriteForbidden( + "2:17: Non-repeated field " + + "\"protobuf_unittest.TestAllTypes.optionalgroup\" " + + "cannot be overwritten.", + "OptionalGroup { a: 1 }\n" + + "OptionalGroup { }\n"); + assertParseErrorWithOverwriteForbidden( + "2:33: Non-repeated field " + + "\"protobuf_unittest.TestAllTypes.optional_nested_message\" " + + "cannot be overwritten.", + "optional_nested_message { }\n" + + "optional_nested_message { bb: 3 }\n"); + assertParseErrorWithOverwriteForbidden( + "2:16: Non-repeated field " + + "\"protobuf_unittest.TestAllTypes.default_int32\" " + + "cannot be overwritten.", + "default_int32: 41\n" + // the default value + "default_int32: 41\n"); + assertParseErrorWithOverwriteForbidden( + "2:17: Non-repeated field " + + "\"protobuf_unittest.TestAllTypes.default_string\" " + + "cannot be overwritten.", + "default_string: \"zxcv\"\n" + + "default_string: \"asdf\"\n"); + } + + public void testParseShortRepeatedFormOfRepeatedFields() throws Exception { + assertParseSuccessWithOverwriteForbidden("repeated_foreign_enum: [FOREIGN_FOO, FOREIGN_BAR]"); + assertParseSuccessWithOverwriteForbidden("repeated_int32: [ 1, 2 ]\n"); + assertParseSuccessWithOverwriteForbidden("RepeatedGroup [{ a: 1 },{ a: 2 }]\n"); + assertParseSuccessWithOverwriteForbidden("repeated_nested_message [{ bb: 1 }, { bb: 2 }]\n"); + } + + public void testParseShortRepeatedFormOfNonRepeatedFields() throws Exception { + assertParseErrorWithOverwriteForbidden( + "1:17: Couldn't parse integer: For input string: \"[\"", + "optional_int32: [1]\n"); + } + + // ======================================================================= + // test oneof + + public void testOneofTextFormat() throws Exception { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + TestUtil.setOneof(builder); + TestOneof2 message = builder.build(); + TestOneof2.Builder dest = TestOneof2.newBuilder(); + TextFormat.merge(TextFormat.printToUnicodeString(message), dest); + TestUtil.assertOneofSet(dest.build()); + } + + public void testOneofOverwriteForbidden() throws Exception { + String input = "foo_string: \"stringvalue\" foo_int: 123"; + TestOneof2.Builder builder = TestOneof2.newBuilder(); + try { + parserWithOverwriteForbidden.merge( + input, TestUtil.getExtensionRegistry(), builder); + fail("Expected parse exception."); + } catch (TextFormat.ParseException e) { + assertEquals("1:36: Field \"protobuf_unittest.TestOneof2.foo_int\"" + + " is specified along with field \"protobuf_unittest.TestOneof2.foo_string\"," + + " another member of oneof \"foo\".", e.getMessage()); + } + } + + public void testOneofOverwriteAllowed() throws Exception { + String input = "foo_string: \"stringvalue\" foo_int: 123"; + TestOneof2.Builder builder = TestOneof2.newBuilder(); + defaultParser.merge(input, TestUtil.getExtensionRegistry(), builder); + // Only the last value sticks. + TestOneof2 oneof = builder.build(); + assertFalse(oneof.hasFooString()); + assertTrue(oneof.hasFooInt()); + } } diff --git a/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java b/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java index ea088b3..d4139d2 100644 --- a/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java +++ b/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java @@ -31,10 +31,13 @@ package com.google.protobuf; import protobuf_unittest.UnittestProto; +import protobuf_unittest.UnittestProto.ForeignEnum; import protobuf_unittest.UnittestProto.TestAllExtensions; import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestEmptyMessage; import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions; +import protobuf_unittest.UnittestProto.TestPackedExtensions; +import protobuf_unittest.UnittestProto.TestPackedTypes; import junit.framework.TestCase; @@ -204,6 +207,13 @@ public class UnknownFieldSetTest extends TestCase { TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).clear().build(); assertEquals(0, message.getSerializedSize()); } + + public void testClearField() throws Exception { + int fieldNumber = unknownFields.asMap().keySet().iterator().next(); + UnknownFieldSet fields = + UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clearField(fieldNumber).build(); + assertFalse(fields.hasField(fieldNumber)); + } public void testParseKnownAndUnknown() throws Exception { // Test mixing known and unknown fields when parsing. @@ -434,4 +444,210 @@ public class UnknownFieldSetTest extends TestCase { assertEquals(copy, set); assertEquals(set.hashCode(), copy.hashCode()); } + + // ================================================================= + + public void testSerializeLite() throws Exception { + UnittestLite.TestEmptyMessageLite emptyMessageLite = + UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData); + assertEquals(allFieldsData.size(), emptyMessageLite.getSerializedSize()); + ByteString data = emptyMessageLite.toByteString(); + TestAllTypes message = TestAllTypes.parseFrom(data); + TestUtil.assertAllFieldsSet(message); + assertEquals(allFieldsData, data); + } + + public void testAllExtensionsLite() throws Exception { + TestAllExtensions allExtensions = TestUtil.getAllExtensionsSet(); + ByteString allExtensionsData = allExtensions.toByteString(); + UnittestLite.TestEmptyMessageLite emptyMessageLite = + UnittestLite.TestEmptyMessageLite.PARSER.parseFrom(allExtensionsData); + ByteString data = emptyMessageLite.toByteString(); + TestAllExtensions message = + TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry()); + TestUtil.assertAllExtensionsSet(message); + assertEquals(allExtensionsData, data); + } + + public void testAllPackedFieldsLite() throws Exception { + TestPackedTypes allPackedFields = TestUtil.getPackedSet(); + ByteString allPackedData = allPackedFields.toByteString(); + UnittestLite.TestEmptyMessageLite emptyMessageLite = + UnittestLite.TestEmptyMessageLite.parseFrom(allPackedData); + ByteString data = emptyMessageLite.toByteString(); + TestPackedTypes message = + TestPackedTypes.parseFrom(data, TestUtil.getExtensionRegistry()); + TestUtil.assertPackedFieldsSet(message); + assertEquals(allPackedData, data); + } + + public void testAllPackedExtensionsLite() throws Exception { + TestPackedExtensions allPackedExtensions = TestUtil.getPackedExtensionsSet(); + ByteString allPackedExtensionsData = allPackedExtensions.toByteString(); + UnittestLite.TestEmptyMessageLite emptyMessageLite = + UnittestLite.TestEmptyMessageLite.parseFrom(allPackedExtensionsData); + ByteString data = emptyMessageLite.toByteString(); + TestPackedExtensions message = + TestPackedExtensions.parseFrom(data, TestUtil.getExtensionRegistry()); + TestUtil.assertPackedExtensionsSet(message); + assertEquals(allPackedExtensionsData, data); + } + + public void testCopyFromLite() throws Exception { + UnittestLite.TestEmptyMessageLite emptyMessageLite = + UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData); + UnittestLite.TestEmptyMessageLite emptyMessageLite2 = + UnittestLite.TestEmptyMessageLite.newBuilder() + .mergeFrom(emptyMessageLite).build(); + assertEquals(emptyMessageLite.toByteString(), emptyMessageLite2.toByteString()); + } + + public void testMergeFromLite() throws Exception { + TestAllTypes message1 = TestAllTypes.newBuilder() + .setOptionalInt32(1) + .setOptionalString("foo") + .addRepeatedString("bar") + .setOptionalNestedEnum(TestAllTypes.NestedEnum.BAZ) + .build(); + + TestAllTypes message2 = TestAllTypes.newBuilder() + .setOptionalInt64(2) + .setOptionalString("baz") + .addRepeatedString("qux") + .setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ) + .build(); + + ByteString data1 = message1.toByteString(); + UnittestLite.TestEmptyMessageLite emptyMessageLite1 = + UnittestLite.TestEmptyMessageLite.parseFrom(data1); + ByteString data2 = message2.toByteString(); + UnittestLite.TestEmptyMessageLite emptyMessageLite2 = + UnittestLite.TestEmptyMessageLite.parseFrom(data2); + + message1 = TestAllTypes.newBuilder(message1).mergeFrom(message2).build(); + emptyMessageLite1 = UnittestLite.TestEmptyMessageLite.newBuilder(emptyMessageLite1) + .mergeFrom(emptyMessageLite2).build(); + + data1 = emptyMessageLite1.toByteString(); + message2 = TestAllTypes.parseFrom(data1); + + assertEquals(message1, message2); + } + + public void testWrongTypeTreatedAsUnknownLite() throws Exception { + // Test that fields of the wrong wire type are treated like unknown fields + // when parsing. + + ByteString bizarroData = getBizarroData(); + TestAllTypes allTypesMessage = TestAllTypes.parseFrom(bizarroData); + UnittestLite.TestEmptyMessageLite emptyMessageLite = + UnittestLite.TestEmptyMessageLite.parseFrom(bizarroData); + ByteString data = emptyMessageLite.toByteString(); + TestAllTypes allTypesMessage2 = TestAllTypes.parseFrom(data); + + assertEquals(allTypesMessage.toString(), allTypesMessage2.toString()); + } + + public void testUnknownExtensionsLite() throws Exception { + // Make sure fields are properly parsed to the UnknownFieldSet even when + // they are declared as extension numbers. + + UnittestLite.TestEmptyMessageWithExtensionsLite message = + UnittestLite.TestEmptyMessageWithExtensionsLite.parseFrom(allFieldsData); + + assertEquals(allFieldsData, message.toByteString()); + } + + public void testWrongExtensionTypeTreatedAsUnknownLite() throws Exception { + // Test that fields of the wrong wire type are treated like unknown fields + // when parsing extensions. + + ByteString bizarroData = getBizarroData(); + TestAllExtensions allExtensionsMessage = + TestAllExtensions.parseFrom(bizarroData); + UnittestLite.TestEmptyMessageLite emptyMessageLite = + UnittestLite.TestEmptyMessageLite.parseFrom(bizarroData); + + // All fields should have been interpreted as unknown, so the byte strings + // should be the same. + assertEquals(emptyMessageLite.toByteString(), + allExtensionsMessage.toByteString()); + } + + public void testParseUnknownEnumValueLite() throws Exception { + Descriptors.FieldDescriptor singularField = + TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum"); + Descriptors.FieldDescriptor repeatedField = + TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum"); + assertNotNull(singularField); + assertNotNull(repeatedField); + + ByteString data = + UnknownFieldSet.newBuilder() + .addField(singularField.getNumber(), + UnknownFieldSet.Field.newBuilder() + .addVarint(TestAllTypes.NestedEnum.BAR.getNumber()) + .addVarint(5) // not valid + .build()) + .addField(repeatedField.getNumber(), + UnknownFieldSet.Field.newBuilder() + .addVarint(TestAllTypes.NestedEnum.FOO.getNumber()) + .addVarint(4) // not valid + .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber()) + .addVarint(6) // not valid + .build()) + .build() + .toByteString(); + + UnittestLite.TestEmptyMessageLite emptyMessageLite = + UnittestLite.TestEmptyMessageLite.parseFrom(data); + data = emptyMessageLite.toByteString(); + + { + TestAllTypes message = TestAllTypes.parseFrom(data); + assertEquals(TestAllTypes.NestedEnum.BAR, + message.getOptionalNestedEnum()); + assertEquals( + Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ), + message.getRepeatedNestedEnumList()); + assertEquals(Arrays.asList(5L), + message.getUnknownFields() + .getField(singularField.getNumber()) + .getVarintList()); + assertEquals(Arrays.asList(4L, 6L), + message.getUnknownFields() + .getField(repeatedField.getNumber()) + .getVarintList()); + } + + { + TestAllExtensions message = + TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry()); + assertEquals(TestAllTypes.NestedEnum.BAR, + message.getExtension(UnittestProto.optionalNestedEnumExtension)); + assertEquals( + Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ), + message.getExtension(UnittestProto.repeatedNestedEnumExtension)); + assertEquals(Arrays.asList(5L), + message.getUnknownFields() + .getField(singularField.getNumber()) + .getVarintList()); + assertEquals(Arrays.asList(4L, 6L), + message.getUnknownFields() + .getField(repeatedField.getNumber()) + .getVarintList()); + } + } + + public void testClearLite() throws Exception { + UnittestLite.TestEmptyMessageLite emptyMessageLite1 = + UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData); + UnittestLite.TestEmptyMessageLite emptyMessageLite2 = + UnittestLite.TestEmptyMessageLite.newBuilder() + .mergeFrom(emptyMessageLite1).clear().build(); + assertEquals(0, emptyMessageLite2.getSerializedSize()); + ByteString data = emptyMessageLite2.toByteString(); + assertEquals(0, data.size()); + } + } diff --git a/java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java b/java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java new file mode 100644 index 0000000..ad4bbf8 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java @@ -0,0 +1,227 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import junit.framework.TestCase; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +/** + * Tests for {@link UnmodifiableLazyStringList}. + * + * @author jonp@google.com (Jon Perlow) + */ +public class UnmodifiableLazyStringListTest extends TestCase { + + private static String STRING_A = "A"; + private static String STRING_B = "B"; + private static String STRING_C = "C"; + + private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A"); + private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B"); + private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C"); + + public void testReadOnlyMethods() { + LazyStringArrayList rawList = createSampleList(); + UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList); + assertEquals(3, list.size()); + assertSame(STRING_A, list.get(0)); + assertSame(STRING_B, list.get(1)); + assertSame(STRING_C, list.get(2)); + assertEquals(BYTE_STRING_A, list.getByteString(0)); + assertEquals(BYTE_STRING_B, list.getByteString(1)); + assertEquals(BYTE_STRING_C, list.getByteString(2)); + + List byteStringList = list.asByteStringList(); + assertSame(list.getByteString(0), byteStringList.get(0)); + assertSame(list.getByteString(1), byteStringList.get(1)); + assertSame(list.getByteString(2), byteStringList.get(2)); + } + + public void testModifyMethods() { + LazyStringArrayList rawList = createSampleList(); + UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList); + + try { + list.remove(0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(3, list.size()); + + try { + list.add(STRING_B); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(3, list.size()); + + try { + list.set(1, STRING_B); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(3, list.size()); + + List byteStringList = list.asByteStringList(); + try { + byteStringList.remove(0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(3, list.size()); + assertEquals(3, byteStringList.size()); + + try { + byteStringList.add(BYTE_STRING_B); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(3, list.size()); + assertEquals(3, byteStringList.size()); + + try { + byteStringList.set(1, BYTE_STRING_B); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(3, list.size()); + assertEquals(3, byteStringList.size()); + } + + public void testIterator() { + LazyStringArrayList rawList = createSampleList(); + UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList); + + Iterator iter = list.iterator(); + int count = 0; + while (iter.hasNext()) { + iter.next(); + count++; + try { + iter.remove(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + assertEquals(3, count); + + List byteStringList = list.asByteStringList(); + Iterator byteIter = byteStringList.iterator(); + count = 0; + while (byteIter.hasNext()) { + byteIter.next(); + count++; + try { + byteIter.remove(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + assertEquals(3, count); + } + + public void testListIterator() { + LazyStringArrayList rawList = createSampleList(); + UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList); + + ListIterator iter = list.listIterator(); + int count = 0; + while (iter.hasNext()) { + iter.next(); + count++; + try { + iter.remove(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + iter.set("bar"); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + iter.add("bar"); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + assertEquals(3, count); + + List byteStringList = list.asByteStringList(); + ListIterator byteIter = byteStringList.listIterator(); + count = 0; + while (byteIter.hasNext()) { + byteIter.next(); + count++; + try { + byteIter.remove(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + byteIter.set(BYTE_STRING_A); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + byteIter.add(BYTE_STRING_A); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + assertEquals(3, count); + } + + private LazyStringArrayList createSampleList() { + LazyStringArrayList rawList = new LazyStringArrayList(); + rawList.add(STRING_A); + rawList.add(STRING_B); + rawList.add(STRING_C); + return rawList; + } +} diff --git a/java/src/test/java/com/google/protobuf/WireFormatTest.java b/java/src/test/java/com/google/protobuf/WireFormatTest.java index 5ea1dd6..146029d 100644 --- a/java/src/test/java/com/google/protobuf/WireFormatTest.java +++ b/java/src/test/java/com/google/protobuf/WireFormatTest.java @@ -34,11 +34,14 @@ import junit.framework.TestCase; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.util.List; import protobuf_unittest.UnittestProto; import protobuf_unittest.UnittestProto.TestAllExtensions; import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestFieldOrderings; +import protobuf_unittest.UnittestProto.TestOneof2; +import protobuf_unittest.UnittestProto.TestOneofBackwardsCompatible; import protobuf_unittest.UnittestProto.TestPackedExtensions; import protobuf_unittest.UnittestProto.TestPackedTypes; import protobuf_unittest.UnittestMset.TestMessageSet; @@ -217,8 +220,8 @@ public class WireFormatTest extends TestCase { } public void testExtensionsSerializedSize() throws Exception { - assertEquals(TestUtil.getAllSet().getSerializedSize(), - TestUtil.getAllExtensionsSet().getSerializedSize()); + assertNotSame(TestUtil.getAllSet().getSerializedSize(), + TestUtil.getAllExtensionsSet().getSerializedSize()); } public void testSerializeDelimited() throws Exception { @@ -328,7 +331,17 @@ public class WireFormatTest extends TestCase { private static final int TYPE_ID_2 = TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber(); - public void testSerializeMessageSet() throws Exception { + public void testSerializeMessageSetEagerly() throws Exception { + testSerializeMessageSetWithFlag(true); + } + + public void testSerializeMessageSetNotEagerly() throws Exception { + testSerializeMessageSetWithFlag(false); + } + + private void testSerializeMessageSetWithFlag(boolean eagerParsing) + throws Exception { + ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); // Set up a TestMessageSet with two known messages and an unknown one. TestMessageSet messageSet = TestMessageSet.newBuilder() @@ -372,7 +385,17 @@ public class WireFormatTest extends TestCase { assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8()); } - public void testParseMessageSet() throws Exception { + public void testParseMessageSetEagerly() throws Exception { + testParseMessageSetWithFlag(true); + } + + public void testParseMessageSetNotEagerly()throws Exception { + testParseMessageSetWithFlag(false); + } + + private void testParseMessageSetWithFlag(boolean eagerParsing) + throws Exception { + ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); extensionRegistry.add(TestMessageSetExtension2.messageSetExtension); @@ -424,4 +447,160 @@ public class WireFormatTest extends TestCase { assertEquals(1, field.getLengthDelimitedList().size()); assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8()); } + + public void testParseMessageSetExtensionEagerly() throws Exception { + testParseMessageSetExtensionWithFlag(true); + } + + public void testParseMessageSetExtensionNotEagerly() throws Exception { + testParseMessageSetExtensionWithFlag(false); + } + + private void testParseMessageSetExtensionWithFlag(boolean eagerParsing) + throws Exception { + ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); + ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); + extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); + + // Set up a RawMessageSet with a known messages. + int TYPE_ID_1 = + TestMessageSetExtension1 + .getDescriptor().getExtensions().get(0).getNumber(); + RawMessageSet raw = + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(TYPE_ID_1) + .setMessage( + TestMessageSetExtension1.newBuilder() + .setI(123) + .build().toByteString()) + .build()) + .build(); + + ByteString data = raw.toByteString(); + + // Parse as a TestMessageSet and check the contents. + TestMessageSet messageSet = + TestMessageSet.parseFrom(data, extensionRegistry); + assertEquals(123, messageSet.getExtension( + TestMessageSetExtension1.messageSetExtension).getI()); + } + + public void testMergeLazyMessageSetExtensionEagerly() throws Exception { + testMergeLazyMessageSetExtensionWithFlag(true); + } + + public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception { + testMergeLazyMessageSetExtensionWithFlag(false); + } + + private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing) + throws Exception { + ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); + ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); + extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); + + // Set up a RawMessageSet with a known messages. + int TYPE_ID_1 = + TestMessageSetExtension1 + .getDescriptor().getExtensions().get(0).getNumber(); + RawMessageSet raw = + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(TYPE_ID_1) + .setMessage( + TestMessageSetExtension1.newBuilder() + .setI(123) + .build().toByteString()) + .build()) + .build(); + + ByteString data = raw.toByteString(); + + // Parse as a TestMessageSet and store value into lazy field + TestMessageSet messageSet = + TestMessageSet.parseFrom(data, extensionRegistry); + // Merge lazy field check the contents. + messageSet = + messageSet.toBuilder().mergeFrom(data, extensionRegistry).build(); + assertEquals(123, messageSet.getExtension( + TestMessageSetExtension1.messageSetExtension).getI()); + } + + public void testMergeMessageSetExtensionEagerly() throws Exception { + testMergeMessageSetExtensionWithFlag(true); + } + + public void testMergeMessageSetExtensionNotEagerly() throws Exception { + testMergeMessageSetExtensionWithFlag(false); + } + + private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing) + throws Exception { + ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); + ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); + extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); + + // Set up a RawMessageSet with a known messages. + int TYPE_ID_1 = + TestMessageSetExtension1 + .getDescriptor().getExtensions().get(0).getNumber(); + RawMessageSet raw = + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(TYPE_ID_1) + .setMessage( + TestMessageSetExtension1.newBuilder() + .setI(123) + .build().toByteString()) + .build()) + .build(); + + // Serialize RawMessageSet unnormally (message value before type id) + ByteString.CodedBuilder out = ByteString.newCodedBuilder( + raw.getSerializedSize()); + CodedOutputStream output = out.getCodedOutput(); + List items = raw.getItemList(); + for (int i = 0; i < items.size(); i++) { + RawMessageSet.Item item = items.get(i); + output.writeTag(1, WireFormat.WIRETYPE_START_GROUP); + output.writeBytes(3, item.getMessage()); + output.writeInt32(2, item.getTypeId()); + output.writeTag(1, WireFormat.WIRETYPE_END_GROUP); + } + ByteString data = out.build(); + + // Merge bytes into TestMessageSet and check the contents. + TestMessageSet messageSet = + TestMessageSet.newBuilder().mergeFrom(data, extensionRegistry).build(); + assertEquals(123, messageSet.getExtension( + TestMessageSetExtension1.messageSetExtension).getI()); + } + + // ================================================================ + // oneof + public void testOneofWireFormat() throws Exception { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + TestUtil.setOneof(builder); + TestOneof2 message = builder.build(); + ByteString rawBytes = message.toByteString(); + + assertEquals(rawBytes.size(), message.getSerializedSize()); + + TestOneof2 message2 = TestOneof2.parseFrom(rawBytes); + TestUtil.assertOneofSet(message2); + } + + public void testOneofOnlyLastSet() throws Exception { + TestOneofBackwardsCompatible source = TestOneofBackwardsCompatible + .newBuilder().setFooInt(100).setFooString("101").build(); + + ByteString rawBytes = source.toByteString(); + TestOneof2 message = TestOneof2.parseFrom(rawBytes); + assertFalse(message.hasFooInt()); + assertTrue(message.hasFooString()); + } } diff --git a/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto b/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto new file mode 100644 index 0000000..8801db9 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto @@ -0,0 +1,61 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: Naoki Iwasaki (niwasaki@google.com) +// +// A proto file with lazy fields + + +package protobuf_unittest; + +option optimize_for = LITE_RUNTIME; + +message LazyMessageLite { + optional int32 num = 1; + optional int32 num_with_default = 2 [default = 421]; + optional LazyInnerMessageLite inner = 3 [lazy = true]; + repeated LazyInnerMessageLite repeated_inner = 4 [lazy = true]; + + oneof oneof_field { + int32 oneof_num = 5; + LazyInnerMessageLite oneof_inner = 6 [lazy = true]; + } +} + +message LazyInnerMessageLite { + optional int32 num = 1; + optional int32 num_with_default = 2 [default = 42]; + optional LazyNestedInnerMessageLite nested = 3 [lazy = true]; +} + +message LazyNestedInnerMessageLite { + optional int32 num = 1; + optional int32 num_with_default = 2 [default = 4]; +} diff --git a/java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto b/java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto new file mode 100644 index 0000000..8b18f07 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto @@ -0,0 +1,55 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: pbogle@google.com (Phil Bogle) + + +package protobuf_unittest.lite_equals_and_hash; + +// This proto definition is used to test that java_generate_equals_and_hash +// works correctly with the LITE_RUNTIME. +option java_generate_equals_and_hash = true; +option optimize_for = LITE_RUNTIME; + +message Foo { + optional int32 value = 1; + repeated Bar bar = 2; +} + +message Bar { + optional string name = 1; +} + +message BarPrime { + optional string name = 1; +} + +message Empty { +} diff --git a/java/src/test/java/com/google/protobuf/multiple_files_test.proto b/java/src/test/java/com/google/protobuf/multiple_files_test.proto index 060f159..401e168 100644 --- a/java/src/test/java/com/google/protobuf/multiple_files_test.proto +++ b/java/src/test/java/com/google/protobuf/multiple_files_test.proto @@ -33,13 +33,19 @@ // A proto file which tests the java_multiple_files option. +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option java_generic_services = true; // auto-added + import "google/protobuf/unittest.proto"; +import "google/protobuf/descriptor.proto"; package protobuf_unittest; option java_multiple_files = true; option java_outer_classname = "MultipleFilesTestProto"; + message MessageWithNoOuter { message NestedMessage { optional int32 i = 1; @@ -53,8 +59,12 @@ message MessageWithNoOuter { optional EnumWithNoOuter foreign_enum = 4; } +extend google.protobuf.EnumValueOptions { + optional int32 enum_value_option = 7654321; +} + enum EnumWithNoOuter { - FOO = 1; + FOO = 1 [(enum_value_option) = 12345]; BAR = 2; } diff --git a/java/src/test/java/com/google/protobuf/nested_builders_test.proto b/java/src/test/java/com/google/protobuf/nested_builders_test.proto new file mode 100644 index 0000000..abffb9d --- /dev/null +++ b/java/src/test/java/com/google/protobuf/nested_builders_test.proto @@ -0,0 +1,53 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: jonp@google.com (Jon Perlow) +// + +package protobuf_unittest; + +option java_multiple_files = true; +option java_outer_classname = "NestedBuilders"; + + +message Vehicle { + optional Engine engine = 1; + repeated Wheel wheel = 2; +} + +message Engine { + optional int32 cylinder = 1; + optional int32 liters = 2; +} + +message Wheel { + optional int32 radius = 1; + optional int32 width = 2; +} diff --git a/java/src/test/java/com/google/protobuf/nested_extension.proto b/java/src/test/java/com/google/protobuf/nested_extension.proto new file mode 100644 index 0000000..777db03 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/nested_extension.proto @@ -0,0 +1,46 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: Darick Tong (darick@google.com) +// +// A proto file with nested extensions. Note that this must be defined in +// a separate file to properly test the initialization of the outer class. + + +import "com/google/protobuf/non_nested_extension.proto"; + +package protobuf_unittest; + + +message MyNestedExtension { + extend MessageToBeExtended { + optional MessageToBeExtended recursiveExtension = 2; + } +} diff --git a/java/src/test/java/com/google/protobuf/nested_extension_lite.proto b/java/src/test/java/com/google/protobuf/nested_extension_lite.proto new file mode 100644 index 0000000..16ee46e --- /dev/null +++ b/java/src/test/java/com/google/protobuf/nested_extension_lite.proto @@ -0,0 +1,48 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: Darick Tong (darick@google.com) +// +// A proto file with nested extensions for a MessageLite messages. Note that +// this must be defined in a separate file to properly test the initialization +// of the outer class. + + +package protobuf_unittest; + +option optimize_for = LITE_RUNTIME; + +import "com/google/protobuf/non_nested_extension_lite.proto"; + +message MyNestedExtensionLite { + extend MessageLiteToBeExtended { + optional MessageLiteToBeExtended recursiveExtensionLite = 3; + } +} diff --git a/java/src/test/java/com/google/protobuf/non_nested_extension.proto b/java/src/test/java/com/google/protobuf/non_nested_extension.proto new file mode 100644 index 0000000..17c0b62 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/non_nested_extension.proto @@ -0,0 +1,49 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: Darick Tong (darick@google.com) +// +// A proto file with extensions. + + +package protobuf_unittest; + + +message MessageToBeExtended { + extensions 1 to max; +} + +message MyNonNestedExtension { +} + +extend MessageToBeExtended { + optional MyNonNestedExtension nonNestedExtension = 1; +} + diff --git a/java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto b/java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto new file mode 100644 index 0000000..3c82659 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto @@ -0,0 +1,50 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: Darick Tong (darick@google.com) +// +// A proto file with extensions for a MessageLite messages. + + +package protobuf_unittest; + +option optimize_for = LITE_RUNTIME; + +message MessageLiteToBeExtended { + extensions 1 to max; +} + +message MyNonNestedExtensionLite { +} + +extend MessageLiteToBeExtended { + optional MyNonNestedExtensionLite nonNestedExtensionLite = 1; +} + diff --git a/java/src/test/java/com/google/protobuf/outer_class_name_test.proto b/java/src/test/java/com/google/protobuf/outer_class_name_test.proto new file mode 100644 index 0000000..2c251e5 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/outer_class_name_test.proto @@ -0,0 +1,38 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package protobuf_unittest; + + +// This message's name is the same with the default outer class name of this +// proto file. It's used to test if the compiler can avoid this conflict +// correctly. +message OuterClassNameTest { +} diff --git a/java/src/test/java/com/google/protobuf/outer_class_name_test2.proto b/java/src/test/java/com/google/protobuf/outer_class_name_test2.proto new file mode 100644 index 0000000..98b5b7a --- /dev/null +++ b/java/src/test/java/com/google/protobuf/outer_class_name_test2.proto @@ -0,0 +1,42 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package protobuf_unittest; + + +message TestMessage2 { + message NestedMessage { + // This message's name is the same with the default outer class name of this + // proto file. It's used to test if the compiler can avoid this conflict + // correctly. + message OuterClassNameTest2 { + } + } +} diff --git a/java/src/test/java/com/google/protobuf/outer_class_name_test3.proto b/java/src/test/java/com/google/protobuf/outer_class_name_test3.proto new file mode 100644 index 0000000..22fb1e6 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/outer_class_name_test3.proto @@ -0,0 +1,43 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package protobuf_unittest; + + +message TestMessage3 { + message NestedMessage { + // This enum's name is the same with the default outer class name of this + // proto file. It's used to test if the compiler can avoid this conflict + // correctly. + enum OuterClassNameTest3 { + DUMMY_VALUE = 1; + } + } +} diff --git a/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto b/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto new file mode 100644 index 0000000..97f2712 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto @@ -0,0 +1,157 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: jonp@google.com (Jon Perlow) + +// This file tests that various identifiers work as field and type names even +// though the same identifiers are used internally by the java code generator. + + +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option java_generic_services = true; // auto-added + +package io_protocol_tests; + +option java_package = "com.google.protobuf"; +option java_outer_classname = "TestBadIdentifiersProto"; +option java_generate_equals_and_hash = true; + +message TestMessage { + optional string cached_size = 1; + optional string serialized_size = 2; + optional string class = 3; +} + +message Descriptor { + option no_standard_descriptor_accessor = true; + optional string descriptor = 1; + message NestedDescriptor { + option no_standard_descriptor_accessor = true; + optional string descriptor = 1; + } + optional NestedDescriptor nested_descriptor = 2; + enum NestedEnum { + FOO = 1; + } +} + +message Parser { + enum ParserEnum { + PARSER = 1; + } + optional ParserEnum parser = 1; +} + +message Deprecated { + enum TestEnum { + FOO = 1; + + // Test if @Deprecated annotation conflicts with Deprecated message name. + BAR = 2 [ deprecated = true ]; + } + + optional int32 field1 = 1 [deprecated=true]; + optional TestEnum field2 = 2 [deprecated=true]; + optional TestMessage field3 = 3 [deprecated=true]; +} + +message Override { + optional int32 override = 1; +} + +message Object { + optional int32 object = 1; + optional string string_object = 2; +} + +message String { + optional string string = 1; +} + +message Integer { + optional int32 integer = 1; +} + +message Long { + optional int32 long = 1; +} + +message Float { + optional float float = 1; +} + +message Double { + optional double double = 1; +} + +service TestConflictingMethodNames { + rpc Override(TestMessage) returns (TestMessage); +} + +message TestConflictingFieldNames { + enum TestEnum { + FOO = 1; + } + message TestMessage { + } + repeated int32 int32_field = 1; + repeated TestEnum enum_field = 2; + repeated string string_field = 3; + repeated bytes bytes_field = 4; + repeated TestMessage message_field = 5; + + optional int32 int32_field_count = 11; + optional TestEnum enum_field_count = 12; + optional string string_field_count = 13; + optional bytes bytes_field_count = 14; + optional TestMessage message_field_count = 15; + + repeated int32 Int32Field = 21; + repeated TestEnum EnumField = 22; + repeated string StringField = 23; + repeated bytes BytesField = 24; + repeated TestMessage MessageField = 25; + + // This field conflicts with "int32_field" as they both generate + // the method getInt32FieldList(). + required int32 int32_field_list = 31; + + extensions 1000 to max; + + repeated int64 int64_field = 41; + extend TestConflictingFieldNames { + // We don't generate accessors for extensions so the following extension + // fields don't conflict with the repeated field "int64_field". + optional int64 int64_field_count = 1001; + optional int64 int64_field_list = 1002; + } +} + diff --git a/java/src/test/java/com/google/protobuf/test_check_utf8.proto b/java/src/test/java/com/google/protobuf/test_check_utf8.proto new file mode 100644 index 0000000..c327ed6 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/test_check_utf8.proto @@ -0,0 +1,50 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: Jacob Butcher (jbaum@google.com) +// +// Test file option java_string_check_utf8. + +package proto2_test_check_utf8; + +option java_outer_classname = "TestCheckUtf8"; +option java_string_check_utf8 = true; + +message StringWrapper { + required string req = 1; + optional string opt = 2; + repeated string rep = 3; +} + +message BytesWrapper { + required bytes req = 1; + optional bytes opt = 2; + repeated bytes rep = 3; +} diff --git a/java/src/test/java/com/google/protobuf/test_check_utf8_size.proto b/java/src/test/java/com/google/protobuf/test_check_utf8_size.proto new file mode 100644 index 0000000..591bc56 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/test_check_utf8_size.proto @@ -0,0 +1,51 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: Jacob Butcher (jbaum@google.com) +// +// Test file option java_string_check_utf8. + +package proto2_test_check_utf8_size; + +option java_outer_classname = "TestCheckUtf8Size"; +option java_string_check_utf8 = true; +option optimize_for = CODE_SIZE; + +message StringWrapperSize { + required string req = 1; + optional string opt = 2; + repeated string rep = 3; +} + +message BytesWrapperSize { + required bytes req = 1; + optional bytes opt = 2; + repeated bytes rep = 3; +} diff --git a/java/src/test/java/com/google/protobuf/test_custom_options.proto b/java/src/test/java/com/google/protobuf/test_custom_options.proto new file mode 100644 index 0000000..f509d29 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/test_custom_options.proto @@ -0,0 +1,43 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: Feng Xiao (xiaofeng@google.com) +// +// Test that custom options defined in a proto file's dependencies are properly +// initialized. + +package protobuf_unittest; + + +import "google/protobuf/unittest_custom_options.proto"; + +message TestMessageWithCustomOptionsContainer { + optional TestMessageWithCustomOptions field = 1; +} diff --git a/java/src/test/java/com/google/protobuf/test_extra_interfaces.proto b/java/src/test/java/com/google/protobuf/test_extra_interfaces.proto new file mode 100644 index 0000000..3d6ce0c --- /dev/null +++ b/java/src/test/java/com/google/protobuf/test_extra_interfaces.proto @@ -0,0 +1,60 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: Darick Tong (darick@google.com) + +package protobuf_unittest; + +message Proto1 { + option experimental_java_message_interface = + "com.google.protobuf.ExtraInterfaces.HasBoolValue"; + + option experimental_java_interface_extends = + "com.google.protobuf.ExtraInterfaces.HasByteValue"; + + option experimental_java_message_interface = + "com.google.protobuf.ExtraInterfaces.HasStringValue"; + + option experimental_java_builder_interface = + "com.google.protobuf.ExtraInterfaces.HasStringValueBuilder" + ""; + + optional string string_value = 1; + optional bool bool_value = 2; + optional bytes byte_value = 3; + optional int32 int_value = 4; +} + +message Proto2 { + option experimental_java_message_interface = + "com.google.protobuf.ExtraInterfaces.HasBoolValue"; + + optional bool bool_value = 1; +} diff --git a/ltmain.sh b/ltmain.sh old mode 100755 new mode 100644 index 174e492..c2852d8 --- a/ltmain.sh +++ b/ltmain.sh @@ -1,9 +1,9 @@ -# Generated from ltmain.m4sh. -# ltmain.sh (GNU libtool) 2.2.4 +# libtool (GNU libtool) 2.4.2 # Written by Gordon Matzigkeit , 1996 -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -32,50 +32,57 @@ # # Provide generalized library-building support services. # -# --config show all configuration variables -# --debug enable verbose shell tracing -# -n, --dry-run display commands without modifying any files -# --features display basic configuration information and exit -# --mode=MODE use operation mode MODE -# --preserve-dup-deps don't remove duplicate dependency libraries -# --quiet, --silent don't print informational messages -# --tag=TAG use configuration variables from tag TAG -# -v, --verbose print informational messages (default) -# --version print version information -# -h, --help print short or long help message +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --no-quiet, --no-silent +# print informational messages (default) +# --no-warn don't display warning messages +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print more informational messages than default +# --no-verbose don't print the extra informational messages +# --version print version information +# -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # -# clean remove files from the build directory -# compile compile a source file into a libtool object -# execute automatically set library path, then run a program -# finish complete the installation of libtool libraries -# install install libraries or executables -# link create a library or an executable -# uninstall remove libraries from an installed directory +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory # -# MODE-ARGS vary depending on the MODE. +# MODE-ARGS vary depending on the MODE. When passed as first option, +# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # -# host-triplet: $host -# shell: $SHELL -# compiler: $LTCC -# compiler flags: $LTCFLAGS -# linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.2.4 -# automake: $automake_version -# autoconf: $autoconf_version +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1ubuntu1 +# automake: $automake_version +# autoconf: $autoconf_version # # Report bugs to . +# GNU libtool home page: . +# General help using GNU software: . -PROGRAM=ltmain.sh +PROGRAM=libtool PACKAGE=libtool -VERSION=2.2.4 +VERSION="2.4.2 Debian-2.4.2-1ubuntu1" TIMESTAMP="" -package_revision=1.2976 +package_revision=1.3337 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then @@ -91,10 +98,15 @@ fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + # NLS nuisances: We save the old values to restore during execute mode. -# Only set LANG and LC_ALL to C if already set. -# These must not be set unconditionally because not all systems understand -# e.g. LANG=C (notably SCO). lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES @@ -107,24 +119,28 @@ do lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done +LC_ALL=C +LANGUAGE=C +export LANGUAGE LC_ALL $lt_unset CDPATH +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" : ${CP="cp -f"} -: ${ECHO="echo"} -: ${EGREP="/usr/bin/grep -E"} -: ${FGREP="/usr/bin/grep -F"} -: ${GREP="/usr/bin/grep"} -: ${LN_S="ln -s"} +test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} -: ${SED="/opt/local/bin/gsed"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} @@ -144,6 +160,27 @@ IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} # func_dirname may be replaced by extended shell implementation + + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "${1}" | $SED "$basename"` +} # func_basename may be replaced by extended shell implementation + + # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: @@ -158,33 +195,183 @@ basename="s,^.*/,," # those functions but instead duplicate the functionality here. func_dirname_and_basename () { - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi - func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` +} # func_dirname_and_basename may be replaced by extended shell implementation + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname may be replaced by extended shell implementation + + +# These SED scripts presuppose an absolute path with a trailing slash. +pathcar='s,^/\([^/]*\).*$,\1,' +pathcdr='s,^/[^/]*,,' +removedotparts=':dotsl + s@/\./@/@g + t dotsl + s,/\.$,/,' +collapseslashes='s@/\{1,\}@/@g' +finalslash='s,/*$,/,' + +# func_normal_abspath PATH +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +# value returned in "$func_normal_abspath_result" +func_normal_abspath () +{ + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` + while :; do + # Processed it all yet? + if test "$func_normal_abspath_tpath" = / ; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result" ; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } -# Generated shell functions inserted here. +# func_relative_path SRCDIR DSTDIR +# generates a relative path from SRCDIR to DSTDIR, with a trailing +# slash if non-empty, suitable for immediately appending a filename +# without needing to append a separator. +# value returned in "$func_relative_path_result" +func_relative_path () +{ + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test "x$func_relative_path_tlibdir" = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath="$0" + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test "x$func_stripname_result" != x ; then + func_relative_path_result=${func_relative_path_result}/${func_stripname_result} + fi + + # Normalisation. If bindir is libdir, return empty string, + # else relative path ending with a slash; either way, target + # file name can be directly appended. + if test ! -z "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} # The name of this program: -# In the unlikely event $progname began with a '-', it would play havoc with -# func_echo (imagine progname=-n), so we prepend ./ in that case: func_dirname_and_basename "$progpath" progname=$func_basename_result -case $progname in - -*) progname=./$progname ;; -esac # Make sure we have an absolute path for reexecution: case $progpath in @@ -196,7 +383,7 @@ case $progpath in ;; *) save_IFS="$IFS" - IFS=: + IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break @@ -215,6 +402,15 @@ sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' + +# Sed substitution that converts a w32 file name or path +# which contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. @@ -243,7 +439,7 @@ opt_warning=: # name if it has been set yet. func_echo () { - $ECHO "$progname${mode+: }$mode: $*" + $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... @@ -258,18 +454,25 @@ func_verbose () : } +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + # func_error arg... # Echo program name prefixed message to standard error. func_error () { - $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2 + $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { - $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2 + $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : @@ -326,9 +529,9 @@ func_mkdir_p () case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop - my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` + my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done - my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` + my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do @@ -378,7 +581,7 @@ func_mktempdir () func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi - $ECHO "X$my_tmpdir" | $Xsed + $ECHO "$my_tmpdir" } @@ -392,7 +595,7 @@ func_quote_for_eval () { case $1 in *[\\\`\"\$]*) - func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; + func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac @@ -419,7 +622,7 @@ func_quote_for_expand () { case $1 in *[\\\`\"]*) - my_arg=`$ECHO "X$1" | $Xsed \ + my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; @@ -488,15 +691,39 @@ func_show_eval_locale () fi } - - +# func_tr_sh +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} # func_version # Echo version message to standard output and exit. func_version () { - $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { + $opt_debug + + $SED -n '/(C)/!b go + :more + /\./!{ + N + s/\n# / / + b more + } + :go + /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ @@ -509,22 +736,28 @@ func_version () # Echo short help message to standard output and exit. func_usage () { - $SED -n '/^# Usage:/,/# -h/ { + $opt_debug + + $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" - $ECHO + echo $ECHO "run \`$progname --help | more' for full usage" exit $? } -# func_help -# Echo long help message to standard output and exit. +# func_help [NOEXIT] +# Echo long help message to standard output and exit, +# unless 'noexit' is passed as argument. func_help () { + $opt_debug + $SED -n '/^# Usage:/,/# Report bugs to/ { + :print s/^# // s/^# *$// s*\$progname*'$progname'* @@ -534,11 +767,18 @@ func_help () s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ - s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ - s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ p - }' < "$progpath" - exit $? + d + } + /^# .* home page:/b print + /^# General help using/b print + ' < "$progpath" + ret=$? + if test -z "$1"; then + exit $ret + fi } # func_missing_arg argname @@ -546,63 +786,106 @@ func_help () # exit_cmd. func_missing_arg () { - func_error "missing argument for $1" + $opt_debug + + func_error "missing argument for $1." exit_cmd=exit } -exit_cmd=: +# func_split_short_opt shortopt +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +func_split_short_opt () +{ + my_sed_short_opt='1s/^\(..\).*$/\1/;q' + my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` + func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` +} # func_split_short_opt may be replaced by extended shell implementation + + +# func_split_long_opt longopt +# Set func_split_long_opt_name and func_split_long_opt_arg shell +# variables after splitting LONGOPT at the `=' sign. +func_split_long_opt () +{ + my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' + my_sed_long_arg='1s/^--[^=]*=//' + + func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` + func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` +} # func_split_long_opt may be replaced by extended shell implementation + +exit_cmd=: -# Check that we have a working $ECHO. -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then - # Yippee, $ECHO works! - : -else - # Restart under the correct shell, and then maybe $ECHO will work. - exec $SHELL "$progpath" --no-reexec ${1+"$@"} -fi -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat </dev/null || echo $max_cmd_len` +} # func_len may be replaced by extended shell implementation + + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` +} # func_lo2o may be replaced by extended shell implementation + + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` +} # func_xform may be replaced by extended shell implementation + + # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. @@ -636,16 +919,16 @@ func_config () # Display the features supported by this script. func_features () { - $ECHO "host: $host" + echo "host: $host" if test "$build_libtool_libs" = yes; then - $ECHO "enable shared libraries" + echo "enable shared libraries" else - $ECHO "disable shared libraries" + echo "disable shared libraries" fi if test "$build_old_libs" = yes; then - $ECHO "enable static libraries" + echo "enable static libraries" else - $ECHO "disable static libraries" + echo "disable static libraries" fi exit $? @@ -692,133 +975,6 @@ func_enable_tag () esac } -# Parse options once, thoroughly. This comes as soon as possible in -# the script to make things like `libtool --version' happen quickly. -{ - - # Shorthand for --mode=foo, only valid as the first argument - case $1 in - clean|clea|cle|cl) - shift; set dummy --mode clean ${1+"$@"}; shift - ;; - compile|compil|compi|comp|com|co|c) - shift; set dummy --mode compile ${1+"$@"}; shift - ;; - execute|execut|execu|exec|exe|ex|e) - shift; set dummy --mode execute ${1+"$@"}; shift - ;; - finish|finis|fini|fin|fi|f) - shift; set dummy --mode finish ${1+"$@"}; shift - ;; - install|instal|insta|inst|ins|in|i) - shift; set dummy --mode install ${1+"$@"}; shift - ;; - link|lin|li|l) - shift; set dummy --mode link ${1+"$@"}; shift - ;; - uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) - shift; set dummy --mode uninstall ${1+"$@"}; shift - ;; - esac - - # Parse non-mode specific arguments: - while test "$#" -gt 0; do - opt="$1" - shift - - case $opt in - --config) func_config ;; - - --debug) preserve_args="$preserve_args $opt" - func_echo "enabling shell trace mode" - opt_debug='set -x' - $opt_debug - ;; - - -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break - execute_dlfiles="$execute_dlfiles $1" - shift - ;; - - --dry-run | -n) opt_dry_run=: ;; - --features) func_features ;; - --finish) mode="finish" ;; - - --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break - case $1 in - # Valid mode arguments: - clean) ;; - compile) ;; - execute) ;; - finish) ;; - install) ;; - link) ;; - relink) ;; - uninstall) ;; - - # Catch anything else as an error - *) func_error "invalid argument for $opt" - exit_cmd=exit - break - ;; - esac - - mode="$1" - shift - ;; - - --preserve-dup-deps) - opt_duplicate_deps=: ;; - - --quiet|--silent) preserve_args="$preserve_args $opt" - opt_silent=: - ;; - - --verbose| -v) preserve_args="$preserve_args $opt" - opt_silent=false - ;; - - --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break - preserve_args="$preserve_args $opt $1" - func_enable_tag "$1" # tagname is set here - shift - ;; - - # Separate optargs to long options: - -dlopen=*|--mode=*|--tag=*) - func_opt_split "$opt" - set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"} - shift - ;; - - -\?|-h) func_usage ;; - --help) opt_help=: ;; - --version) func_version ;; - - -*) func_fatal_help "unrecognized option \`$opt'" ;; - - *) nonopt="$opt" - break - ;; - esac - done - - - case $host in - *cygwin* | *mingw* | *pw32*) - # don't eliminate duplications in $postdeps and $predeps - opt_duplicate_compiler_generated_deps=: - ;; - *) - opt_duplicate_compiler_generated_deps=$opt_duplicate_deps - ;; - esac - - # Having warned about all mis-specified options, bail out if - # anything was wrong. - $exit_cmd $EXIT_FAILURE -} - # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. @@ -855,46 +1011,228 @@ _LT_EOF } -## ----------- ## -## Main. ## -## ----------- ## +# Shorthand for --mode=foo, only valid as the first argument +case $1 in +clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; +compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; +execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; +finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; +install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; +link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; +uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; +esac -$opt_help || { - # Sanity checks first: - func_check_version_match - if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then - func_fatal_configuration "not configured to build any kind of library" - fi - test -z "$mode" && func_fatal_error "error: you must specify a MODE." +# Option defaults: +opt_debug=: +opt_dry_run=false +opt_config=false +opt_preserve_dup_deps=false +opt_features=false +opt_finish=false +opt_help=false +opt_help_all=false +opt_silent=: +opt_warning=: +opt_verbose=: +opt_silent=false +opt_verbose=false + + +# Parse options once, thoroughly. This comes as soon as possible in the +# script to make things like `--version' happen as quickly as we can. +{ + # this just eases exit handling + while test $# -gt 0; do + opt="$1" + shift + case $opt in + --debug|-x) opt_debug='set -x' + func_echo "enabling shell trace mode" + $opt_debug + ;; + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + --config) + opt_config=: +func_config + ;; + --dlopen|-dlopen) + optarg="$1" + opt_dlopen="${opt_dlopen+$opt_dlopen +}$optarg" + shift + ;; + --preserve-dup-deps) + opt_preserve_dup_deps=: + ;; + --features) + opt_features=: +func_features + ;; + --finish) + opt_finish=: +set dummy --mode finish ${1+"$@"}; shift + ;; + --help) + opt_help=: + ;; + --help-all) + opt_help_all=: +opt_help=': help-all' + ;; + --mode) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_mode="$optarg" +case $optarg in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; +esac + shift + ;; + --no-silent|--no-quiet) + opt_silent=false +func_append preserve_args " $opt" + ;; + --no-warning|--no-warn) + opt_warning=false +func_append preserve_args " $opt" + ;; + --no-verbose) + opt_verbose=false +func_append preserve_args " $opt" + ;; + --silent|--quiet) + opt_silent=: +func_append preserve_args " $opt" + opt_verbose=false + ;; + --verbose|-v) + opt_verbose=: +func_append preserve_args " $opt" +opt_silent=false + ;; + --tag) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_tag="$optarg" +func_append preserve_args " $opt $optarg" +func_enable_tag "$optarg" + shift + ;; + + -\?|-h) func_usage ;; + --help) func_help ;; + --version) func_version ;; + # Separate optargs to long options: + --*=*) + func_split_long_opt "$opt" + set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} + shift + ;; - # Darwin sucks - eval std_shrext=\"$shrext_cmds\" + # Separate non-argument short options: + -\?*|-h*|-n*|-v*) + func_split_short_opt "$opt" + set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + --) break ;; + -*) func_fatal_help "unrecognized option \`$opt'" ;; + *) set dummy "$opt" ${1+"$@"}; shift; break ;; + esac + done - # Only execute mode is allowed to have -dlopen flags. - if test -n "$execute_dlfiles" && test "$mode" != execute; then - func_error "unrecognized option \`-dlopen'" - $ECHO "$help" 1>&2 - exit $EXIT_FAILURE + # Validate options: + + # save first non-option argument + if test "$#" -gt 0; then + nonopt="$opt" + shift fi - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$progname --help --mode=$mode' for more information." + # preserve --debug + test "$opt_debug" = : || func_append preserve_args " --debug" + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test "$opt_mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$opt_mode' for more information." + } + + + # Bail if the options were screwed + $exit_cmd $EXIT_FAILURE } + + +## ----------- ## +## Main. ## +## ----------- ## + # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { - $SED -e 4q "$1" 2>/dev/null \ - | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file @@ -907,7 +1245,7 @@ func_lalib_p () func_lalib_unsafe_p () { lalib_p=no - if test -r "$1" && exec 5<&0 <"$1"; then + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line @@ -949,12 +1287,9 @@ func_ltwrapper_executable_p () # temporary ltwrapper_script. func_ltwrapper_scriptname () { - func_ltwrapper_scriptname_result="" - if func_ltwrapper_executable_p "$1"; then - func_dirname_and_basename "$1" "" "." - func_stripname '' '.exe' "$func_basename_result" - func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" - fi + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file @@ -1000,6 +1335,37 @@ func_source () } +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case "$lt_sysroot:$1" in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result="=$func_stripname_result" + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. @@ -1012,13 +1378,15 @@ func_infer_tag () if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do - func_quote_for_eval "$arg" - CC_quoted="$CC_quoted $func_quote_for_eval_result" + func_append_quoted CC_quoted "$arg" done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. - " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;; + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) @@ -1029,11 +1397,13 @@ func_infer_tag () CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. - func_quote_for_eval "$arg" - CC_quoted="$CC_quoted $func_quote_for_eval_result" + func_append_quoted CC_quoted "$arg" done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in - " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. @@ -1058,43 +1428,523 @@ func_infer_tag () } - -# func_write_libtool_object output_name pic_name nonpic_name -# Create a libtool object file (analogous to a ".la" file), -# but don't create it if we're doing a dry run. -func_write_libtool_object () + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$lt_sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $opt_debug + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result="" + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $opt_debug + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $opt_debug + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $opt_debug + if test -z "$2" && test -n "$1" ; then + func_error "Could not determine host file name corresponding to" + func_error " \`$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result="$1" + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $opt_debug + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " \`$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result="$3" + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $opt_debug + case $4 in + $1 ) func_to_host_path_result="$3$func_to_host_path_result" + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via `$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $opt_debug + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $opt_debug + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result="$1" +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result="$func_convert_core_msys_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via `$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $opt_debug + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd="func_convert_path_${func_stripname_result}" + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $opt_debug + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result="$1" +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () { - write_libobj=${1} - if test "$build_libtool_libs" = yes; then - write_lobj=\'${2}\' - else - write_lobj=none - fi - - if test "$build_old_libs" = yes; then - write_oldobj=\'${3}\' - else - write_oldobj=none - fi + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 - $opt_dry_run || { - cat >${write_libobj}T < "$lockfile" fi $opt_dry_run || $RM $removelist - removelist="$removelist $lockfile" + func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 - if test -n "$fix_srcfile_path"; then - eval srcfile=\"$fix_srcfile_path\" - fi + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result @@ -1348,7 +2195,7 @@ compiler." if test -z "$output_obj"; then # Place PIC objects in $objdir - command="$command -o $lobj" + func_append command " -o $lobj" fi func_show_eval_locale "$command" \ @@ -1395,11 +2242,11 @@ compiler." command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then - command="$command -o $obj" + func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. - command="$command$suppress_output" + func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' @@ -1444,13 +2291,13 @@ compiler." } $opt_help || { -test "$mode" = compile && func_mode_compile ${1+"$@"} + test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. - case $mode in + case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. @@ -1481,10 +2328,11 @@ This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes - -prefer-pic try to building PIC objects only - -prefer-non-pic try to building non-PIC objects only + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. @@ -1537,7 +2385,7 @@ either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: - -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." @@ -1557,6 +2405,8 @@ The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) @@ -1585,6 +2435,11 @@ The following components of LINK-COMMAND are treated specially: -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. @@ -1618,18 +2473,44 @@ Otherwise, only FILE itself is deleted using RM." ;; *) - func_fatal_help "invalid operation mode \`$mode'" + func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac - $ECHO + echo $ECHO "Try \`$progname --help' for more information about other modes." - - exit $? } - # Now that we've collected a possible --mode arg, show help if necessary - $opt_help && func_mode_help +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test "$opt_help" = :; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | sed -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + sed '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi # func_mode_execute arg... @@ -1642,13 +2523,16 @@ func_mode_execute () func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. - for file in $execute_dlfiles; do + for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" @@ -1670,7 +2554,7 @@ func_mode_execute () dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then - dir="$dir/$objdir" + func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" @@ -1711,7 +2595,7 @@ func_mode_execute () for file do case $file in - -*) ;; + -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then @@ -1727,8 +2611,7 @@ func_mode_execute () ;; esac # Quote arguments (to preserve shell metacharacters). - func_quote_for_eval "$file" - args="$args $func_quote_for_eval_result" + func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then @@ -1753,29 +2636,66 @@ func_mode_execute () # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" - $ECHO "export $shlibpath_var" + echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } -test "$mode" = execute && func_mode_execute ${1+"$@"} +test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug - libdirs="$nonopt" + libs= + libdirs= admincmds= - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - for dir - do - libdirs="$libdirs $dir" - done + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "\`$opt' is not a valid libtool archive" + fi + else + func_fatal_error "invalid argument \`$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. @@ -1785,7 +2705,7 @@ func_mode_finish () if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" - $opt_dry_run || eval "$cmds" || admincmds="$admincmds + $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done @@ -1794,53 +2714,55 @@ func_mode_finish () # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS - $ECHO "X----------------------------------------------------------------------" | $Xsed - $ECHO "Libraries have been installed in:" - for libdir in $libdirs; do - $ECHO " $libdir" - done - $ECHO - $ECHO "If you ever happen to want to link against installed libraries" - $ECHO "in a given directory, LIBDIR, you must either use libtool, and" - $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'" - $ECHO "flag during linking and do at least one of the following:" - if test -n "$shlibpath_var"; then - $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable" - $ECHO " during execution" - fi - if test -n "$runpath_var"; then - $ECHO " - add LIBDIR to the \`$runpath_var' environment variable" - $ECHO " during linking" - fi - if test -n "$hardcode_libdir_flag_spec"; then - libdir=LIBDIR - eval flag=\"$hardcode_libdir_flag_spec\" + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" - $ECHO " - use the \`$flag' linker flag" - fi - if test -n "$admincmds"; then - $ECHO " - have your system administrator run these commands:$admincmds" - fi - if test -f /etc/ld.so.conf; then - $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" - fi - $ECHO + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo - $ECHO "See any operating system documentation about shared libraries for" - case $host in - solaris2.[6789]|solaris2.1[0-9]) - $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual" - $ECHO "pages." - ;; - *) - $ECHO "more information, such as the ld(1) and ld.so(8) manual pages." - ;; - esac - $ECHO "X----------------------------------------------------------------------" | $Xsed + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi exit $EXIT_SUCCESS } -test "$mode" = finish && func_mode_finish ${1+"$@"} +test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... @@ -1851,7 +2773,7 @@ func_mode_install () # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. - $ECHO "X$nonopt" | $GREP shtool >/dev/null; then + case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " @@ -1865,7 +2787,12 @@ func_mode_install () # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" - install_prog="$install_prog$func_quote_for_eval_result" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac # We need to accept at least all the BSD install flags. dest= @@ -1875,10 +2802,12 @@ func_mode_install () install_type= isdir=no stripme= + no_mode=: for arg do + arg2= if test -n "$dest"; then - files="$files $dest" + func_append files " $dest" dest=$arg continue fi @@ -1886,10 +2815,9 @@ func_mode_install () case $arg in -d) isdir=yes ;; -f) - case " $install_prog " in - *[\\\ /]cp\ *) ;; - *) prev=$arg ;; - esac + if $install_cp; then :; else + prev=$arg + fi ;; -g | -m | -o) prev=$arg @@ -1903,6 +2831,10 @@ func_mode_install () *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then + if test "x$prev" = x-m && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi prev= else dest=$arg @@ -1913,7 +2845,11 @@ func_mode_install () # Aesthetically quote the argument. func_quote_for_eval "$arg" - install_prog="$install_prog $func_quote_for_eval_result" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ @@ -1922,6 +2858,13 @@ func_mode_install () test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" @@ -1976,10 +2919,13 @@ func_mode_install () case $file in *.$libext) # Do the static libraries later. - staticlibs="$staticlibs $file" + func_append staticlibs " $file" ;; *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" @@ -1993,23 +2939,23 @@ func_mode_install () if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; - *) current_libdirs="$current_libdirs $libdir" ;; + *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; - *) future_libdirs="$future_libdirs $libdir" ;; + *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" - dir="$dir$objdir" + func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. - inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that @@ -2022,9 +2968,9 @@ func_mode_install () if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. - relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else - relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" @@ -2042,11 +2988,11 @@ func_mode_install () test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. - func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" @@ -2082,7 +3028,7 @@ func_mode_install () func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. - test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) @@ -2152,7 +3098,7 @@ func_mode_install () # Do a test to see if this is really a libtool program. case $host in - *cygwin*|*mingw*) + *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result @@ -2182,7 +3128,7 @@ func_mode_install () if test -f "$lib"; then func_source "$lib" fi - libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no @@ -2201,7 +3147,7 @@ func_mode_install () file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. - relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" @@ -2220,7 +3166,7 @@ func_mode_install () } else # Install the binary that we compiled earlier. - file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi @@ -2256,11 +3202,13 @@ func_mode_install () # Set up the ranlib parameters. oldlib="$destdir/$name" + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then - func_show_eval "$old_striplib $oldlib" 'exit $?' + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. @@ -2279,7 +3227,7 @@ func_mode_install () fi } -test "$mode" = install && func_mode_install ${1+"$@"} +test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p @@ -2322,6 +3270,22 @@ func_generate_dlsyms () extern \"C\" { #endif +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + /* External symbol declarations for the compiler. */\ " @@ -2331,10 +3295,11 @@ extern \"C\" { $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. - progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do - func_verbose "extracting global C symbols from \`$progfile'" - $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then @@ -2358,7 +3323,7 @@ extern \"C\" { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in - *cygwin* | *mingw* ) + *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; @@ -2370,7 +3335,7 @@ extern \"C\" { eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in - *cygwin | *mingw* ) + *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; @@ -2383,10 +3348,52 @@ extern \"C\" { func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename="" + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname" ; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename="$func_basename_result" + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename" ; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac done $opt_dry_run || { @@ -2414,36 +3421,19 @@ extern \"C\" { if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else - $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi - $ECHO >> "$output_objdir/$my_dlsyms" "\ + echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; -" - case $host in - *cygwin* | *mingw* ) - $ECHO >> "$output_objdir/$my_dlsyms" "\ -/* DATA imports from DLLs on WIN32 con't be const, because - runtime relocations are performed -- see ld's documentation - on pseudo-relocs. */" - lt_dlsym_const= ;; - *osf5*) - echo >> "$output_objdir/$my_dlsyms" "\ -/* This system does not cope well with relocations in const data */" - lt_dlsym_const= ;; - *) - lt_dlsym_const=const ;; - esac - - $ECHO >> "$output_objdir/$my_dlsyms" "\ -extern $lt_dlsym_const lt_dlsymlist +extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; -$lt_dlsym_const lt_dlsymlist +LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," @@ -2456,7 +3446,7 @@ lt_${my_prefix}_LTX_preloaded_symbols[] = eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac - $ECHO >> "$output_objdir/$my_dlsyms" "\ + echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; @@ -2483,7 +3473,7 @@ static const void *lt_preloaded_setup() { # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; @@ -2499,7 +3489,7 @@ static const void *lt_preloaded_setup() { for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; - *) symtab_cflags="$symtab_cflags $arg" ;; + *) func_append symtab_cflags " $arg" ;; esac done @@ -2512,18 +3502,18 @@ static const void *lt_preloaded_setup() { # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in - *cygwin* | *mingw* ) + *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then - compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else - compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) - compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; @@ -2537,8 +3527,8 @@ static const void *lt_preloaded_setup() { # really was required. # Nullify the symbol file. - compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` - finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } @@ -2548,6 +3538,7 @@ static const void *lt_preloaded_setup() { # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug @@ -2558,9 +3549,11 @@ func_win32_libid () win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | - $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then - win32_nmres=`eval $NM -f posix -A $1 | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ @@ -2589,6 +3582,131 @@ func_win32_libid () $ECHO "$win32_libid_type" } +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $opt_debug + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $opt_debug + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive which possess that section. Heuristic: eliminate + # all those which have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $opt_debug + if func_cygming_gnu_implib_p "$1" ; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1" ; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result="" + fi +} # func_extract_an_archive dir oldlib @@ -2597,7 +3715,18 @@ func_extract_an_archive () $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" - func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' + if test "$lock_old_archive_extraction" = yes; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test "$lock_old_archive_extraction" = yes; then + $opt_dry_run || rm -f "$lockfile" + fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else @@ -2668,7 +3797,7 @@ func_extract_archives () darwin_file= darwin_files= for darwin_file in $darwin_filelist; do - darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ @@ -2683,34 +3812,30 @@ func_extract_archives () func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac - my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } - -# func_emit_wrapper arg +# func_emit_wrapper [arg=no] # -# emit a libtool wrapper script on stdout -# don't directly open a file because we may want to +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within -# func_mode_link because it depends on a number of variable +# func_mode_link because it depends on a number of variables # set therein. # -# arg is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is -# the '.lib' directory. This is a cygwin/mingw-specific +# the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { - func_emit_wrapper_arg1=no - if test -n "$1" ; then - func_emit_wrapper_arg1=$1 - fi + func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL @@ -2726,7 +3851,6 @@ func_emit_wrapper () # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. -Xsed='${SED} -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # Be Bourne compatible @@ -2757,31 +3881,135 @@ if test \"\$libtool_install_magic\" = \"$magic\"; then else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then - ECHO=\"$qecho\" - file=\"\$0\" - # Make sure echo works. - if test \"X\$1\" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift - elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then - # Yippee, \$ECHO works! - : - else - # Restart under the correct shell, and then maybe \$ECHO will work. - exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} - fi - fi\ + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ " - $ECHO "\ + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. - thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do - destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then @@ -2791,8 +4019,8 @@ else esac fi - file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into @@ -2805,7 +4033,7 @@ else fi # remove .libs from thisdir case \"\$thisdir\" in - *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi @@ -2860,6 +4088,18 @@ else if test -f \"\$progdir/\$program\"; then" + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ @@ -2868,53 +4108,28 @@ else # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi - # fixup the dll searchpath if we need to. - if test -n "$dllsearchpath"; then - $ECHO "\ - # Add the dll search path components to the executable PATH - PATH=$dllsearchpath:\$PATH -" - fi - $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. -" - case $host in - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2*) - $ECHO "\ - exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} -" - ;; - - *) - $ECHO "\ - exec \"\$progdir/\$program\" \${1+\"\$@\"} -" - ;; - esac - $ECHO "\ - \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 - exit 1 + func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 - $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } -# end: func_emit_wrapper + # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout @@ -2932,20 +4147,18 @@ func_emit_cwrapperexe_src () This wrapper executable should never be moved out of the build directory. If it is, it will not operate correctly. - - Currently, it simply execs the wrapper *script* "$SHELL $output", - but could eventually absorb all of the scripts functionality and - exec $objdir/$outputname directly. */ EOF cat <<"EOF" +#ifdef _MSC_VER +# define _CRT_SECURE_NO_DEPRECATE 1 +#endif #include #include #ifdef _MSC_VER # include # include # include -# define setmode _setmode #else # include # include @@ -2962,6 +4175,44 @@ EOF #include #include +/* declarations of non-ANSI functions */ +#if defined(__MINGW32__) +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined(__CYGWIN__) +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined (other platforms) ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined(_MSC_VER) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +# ifndef _INTPTR_T_DEFINED +# define _INTPTR_T_DEFINED +# define intptr_t int +# endif +#elif defined(__MINGW32__) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined(__CYGWIN__) +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined (other platforms) ... */ +#endif + #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) @@ -2977,14 +4228,7 @@ EOF # define S_IXGRP 0 #endif -#ifdef _MSC_VER -# define S_IXUSR _S_IEXEC -# define stat _stat -# ifndef _INTPTR_T_DEFINED -# define intptr_t int -# endif -#endif - +/* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' @@ -3015,10 +4259,6 @@ EOF # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ -#ifdef __CYGWIN__ -# define FOPEN_WB "wb" -#endif - #ifndef FOPEN_WB # define FOPEN_WB "w" #endif @@ -3031,22 +4271,13 @@ EOF if (stale) { free ((void *) stale); stale = 0; } \ } while (0) -#undef LTWRAPPER_DEBUGPRINTF -#if defined DEBUGWRAPPER -# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args -static void -ltwrapper_debugprintf (const char *fmt, ...) -{ - va_list args; - va_start (args, fmt); - (void) vfprintf (stderr, fmt, args); - va_end (args); -} +#if defined(LT_DEBUGWRAPPER) +static int lt_debug = 1; #else -# define LTWRAPPER_DEBUGPRINTF(args) +static int lt_debug = 0; #endif -const char *program_name = NULL; +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); @@ -3056,37 +4287,88 @@ char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); -void lt_fatal (const char *message, ...); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF -static const char *script_text = + cat </dev/null || echo $SHELL` - case $lt_newargv0 in - *.exe | *.EXE) ;; - *) lt_newargv0=$lt_newargv0.exe ;; - esac - ;; - * ) lt_newargv0=$SHELL ;; - esac - fi - - cat < 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} EOF } # end: func_emit_cwrapperexe_src +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $opt_debug + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + # func_mode_link arg... func_mode_link () { $opt_debug case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra @@ -3554,6 +5133,7 @@ func_mode_link () new_inherited_linker_flags= avoid_version=no + bindir= dlfiles= dlprefiles= dlself=no @@ -3646,6 +5226,11 @@ func_mode_link () esac case $prev in + bindir) + bindir="$arg" + prev= + continue + ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. @@ -3677,9 +5262,9 @@ func_mode_link () ;; *) if test "$prev" = dlfiles; then - dlfiles="$dlfiles $arg" + func_append dlfiles " $arg" else - dlprefiles="$dlprefiles $arg" + func_append dlprefiles " $arg" fi prev= continue @@ -3703,7 +5288,7 @@ func_mode_link () *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; - *) deplibs="$deplibs $qarg.ltframework" # this is fixed later + *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; @@ -3722,7 +5307,7 @@ func_mode_link () moreargs= for fil in `cat "$save_arg"` do -# moreargs="$moreargs $fil" +# func_append moreargs " $fil" arg=$fil # A libtool-controlled object. @@ -3751,7 +5336,7 @@ func_mode_link () if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - dlfiles="$dlfiles $pic_object" + func_append dlfiles " $pic_object" prev= continue else @@ -3763,7 +5348,7 @@ func_mode_link () # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. - dlprefiles="$dlprefiles $pic_object" + func_append dlprefiles " $pic_object" prev= fi @@ -3833,12 +5418,12 @@ func_mode_link () if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; - *) rpath="$rpath $arg" ;; + *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; - *) xrpath="$xrpath $arg" ;; + *) func_append xrpath " $arg" ;; esac fi prev= @@ -3850,28 +5435,28 @@ func_mode_link () continue ;; weak) - weak_libs="$weak_libs $arg" + func_append weak_libs " $arg" prev= continue ;; xcclinker) - linker_flags="$linker_flags $qarg" - compiler_flags="$compiler_flags $qarg" + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) - compiler_flags="$compiler_flags $qarg" + func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) - linker_flags="$linker_flags $qarg" - compiler_flags="$compiler_flags $wl$qarg" + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" @@ -3907,6 +5492,11 @@ func_mode_link () continue ;; + -bindir) + prev=bindir + continue + ;; + -dlopen) prev=dlfiles continue @@ -3957,8 +5547,16 @@ func_mode_link () ;; -L*) - func_stripname '-L' '' "$arg" - dir=$func_stripname_result + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; @@ -3970,22 +5568,30 @@ func_mode_link () ;; esac case "$deplibs " in - *" -L$dir "*) ;; + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; *) - deplibs="$deplibs -L$dir" - lib_search_path="$lib_search_path $dir" + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" ;; esac case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) - testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; - *) dllsearchpath="$dllsearchpath:$dir";; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; - *) dllsearchpath="$dllsearchpath:$testbindir";; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; esac ;; esac @@ -3995,7 +5601,7 @@ func_mode_link () -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; @@ -4009,7 +5615,7 @@ func_mode_link () ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework - deplibs="$deplibs System.ltframework" + func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) @@ -4029,7 +5635,7 @@ func_mode_link () ;; esac fi - deplibs="$deplibs $arg" + func_append deplibs " $arg" continue ;; @@ -4041,21 +5647,22 @@ func_mode_link () # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. - -model|-arch|-isysroot) - compiler_flags="$compiler_flags $arg" + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) - compiler_flags="$compiler_flags $arg" + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; - * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; + * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; @@ -4072,7 +5679,7 @@ func_mode_link () -no-install) case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin*) + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" @@ -4122,13 +5729,17 @@ func_mode_link () # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; - *) xrpath="$xrpath $dir" ;; + *) func_append xrpath " $dir" ;; esac continue ;; @@ -4181,8 +5792,8 @@ func_mode_link () for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" - arg="$arg $wl$func_quote_for_eval_result" - compiler_flags="$compiler_flags $func_quote_for_eval_result" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" @@ -4197,9 +5808,9 @@ func_mode_link () for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" - arg="$arg $wl$func_quote_for_eval_result" - compiler_flags="$compiler_flags $wl$func_quote_for_eval_result" - linker_flags="$linker_flags $func_quote_for_eval_result" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" @@ -4227,23 +5838,27 @@ func_mode_link () arg="$func_quote_for_eval_result" ;; - # -64, -mips[0-9] enable 64-bit mode on the SGI compiler - # -r[0-9][0-9]* specifies the processor on the SGI compiler - # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler - # +DA*, +DD* enable 64-bit mode on the HP compiler - # -q* pass through compiler args for the IBM compiler - # -m*, -t[45]*, -txscale* pass through architecture-specific - # compiler args for GCC - # -F/path gives path to uninstalled frameworks, gcc on darwin - # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC - # @file GCC response files + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ - -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" - compiler_flags="$compiler_flags $arg" + func_append compiler_flags " $arg" continue ;; @@ -4255,7 +5870,7 @@ func_mode_link () *.$objext) # A standard object. - objs="$objs $arg" + func_append objs " $arg" ;; *.lo) @@ -4286,7 +5901,7 @@ func_mode_link () if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - dlfiles="$dlfiles $pic_object" + func_append dlfiles " $pic_object" prev= continue else @@ -4298,7 +5913,7 @@ func_mode_link () # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. - dlprefiles="$dlprefiles $pic_object" + func_append dlprefiles " $pic_object" prev= fi @@ -4343,24 +5958,25 @@ func_mode_link () *.$libext) # An archive. - deplibs="$deplibs $arg" - old_deplibs="$old_deplibs $arg" + func_append deplibs " $arg" + func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. + func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. - dlfiles="$dlfiles $arg" + func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. - dlprefiles="$dlprefiles $arg" + func_append dlprefiles " $func_resolve_sysroot_result" prev= else - deplibs="$deplibs $arg" + func_append deplibs " $func_resolve_sysroot_result" fi continue ;; @@ -4398,7 +6014,7 @@ func_mode_link () if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi @@ -4407,6 +6023,8 @@ func_mode_link () func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" @@ -4427,12 +6045,12 @@ func_mode_link () # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do - if $opt_duplicate_deps ; then + if $opt_preserve_dup_deps ; then case "$libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi - libs="$libs $deplib" + func_append libs " $deplib" done if test "$linkmode" = lib; then @@ -4445,9 +6063,9 @@ func_mode_link () if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in - *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac - pre_post_deps="$pre_post_deps $pre_post_dep" + func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= @@ -4506,7 +6124,10 @@ func_mode_link () case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; - link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then @@ -4514,17 +6135,19 @@ func_mode_link () for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= + func_resolve_sysroot "$lib" case $lib in - *.la) func_source "$lib" ;; + *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do - deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` + func_basename "$deplib" + deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; - *) deplibs="$deplibs $deplib" ;; + *) func_append deplibs " $deplib" ;; esac done done @@ -4540,16 +6163,17 @@ func_mode_link () lib= found=no case $deplib in - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else - compiler_flags="$compiler_flags $deplib" + func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; - * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi @@ -4634,7 +6258,7 @@ func_mode_link () if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; - * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi @@ -4647,7 +6271,8 @@ func_mode_link () test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" - newlib_search_path="$newlib_search_path $func_stripname_result" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then @@ -4661,7 +6286,8 @@ func_mode_link () finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" - newlib_search_path="$newlib_search_path $func_stripname_result" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" @@ -4672,17 +6298,21 @@ func_mode_link () -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" - dir=$func_stripname_result + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; - *) xrpath="$xrpath $dir" ;; + *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; - *.la) lib="$deplib" ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" @@ -4700,7 +6330,7 @@ func_mode_link () match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi @@ -4710,15 +6340,15 @@ func_mode_link () ;; esac if test "$valid_a_lib" != yes; then - $ECHO + echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." - $ECHO "*** I have the capability to make that library automatically link in when" - $ECHO "*** you link to this library. But I can only do this if you have a" - $ECHO "*** shared version of the library, which you do not appear to have" - $ECHO "*** because the file extensions .$libext of this argument makes me believe" - $ECHO "*** that it is just a static archive that I should not use here." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." else - $ECHO + echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" @@ -4745,11 +6375,11 @@ func_mode_link () if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. - newdlprefiles="$newdlprefiles $deplib" + func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else - newdlfiles="$newdlfiles $deplib" + func_append newdlfiles " $deplib" fi fi continue @@ -4791,20 +6421,20 @@ func_mode_link () # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then - tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; - *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi - dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then - test -n "$dlopen" && dlfiles="$dlfiles $dlopen" - test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then @@ -4815,30 +6445,36 @@ func_mode_link () func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. - convenience="$convenience $ladir/$objdir/$old_library" - old_convenience="$old_convenience $ladir/$objdir/$old_library" + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if $opt_duplicate_deps ; then - case "$tmp_libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - tmp_libs="$tmp_libs $deplib" - done continue fi # $pass = conv # Get the name of the library we link against. linklib= - for l in $old_library $library_names; do - linklib="$l" - done + if test -n "$old_library" && + { test "$prefer_static_libs" = yes || + test "$prefer_static_libs,$installed" = "built,no"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib="$l" + done + fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi @@ -4855,9 +6491,9 @@ func_mode_link () # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. - dlprefiles="$dlprefiles $lib $dependency_libs" + func_append dlprefiles " $lib $dependency_libs" else - newdlfiles="$newdlfiles $lib" + func_append newdlfiles " $lib" fi continue fi # $pass = dlopen @@ -4879,14 +6515,14 @@ func_mode_link () # Find the relevant object directory and library name. if test "X$installed" = Xyes; then - if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else - dir="$libdir" - absdir="$libdir" + dir="$lt_sysroot$libdir" + absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else @@ -4894,12 +6530,12 @@ func_mode_link () dir="$ladir" absdir="$abs_ladir" # Remove this search path later - notinst_path="$notinst_path $abs_ladir" + func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later - notinst_path="$notinst_path $abs_ladir" + func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" @@ -4910,20 +6546,46 @@ func_mode_link () if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - newdlprefiles="$newdlprefiles $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" - # Otherwise, use the dlname, so that lt_dlopen finds it. - elif test -n "$dlname"; then - newdlprefiles="$newdlprefiles $dir/$dlname" - else - newdlprefiles="$newdlprefiles $dir/$linklib" - fi + case "$host" in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac fi # $pass = dlpreopen if test -z "$libdir"; then @@ -4941,7 +6603,7 @@ func_mode_link () if test "$linkmode" = prog && test "$pass" != link; then - newlib_search_path="$newlib_search_path $ladir" + func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no @@ -4954,7 +6616,8 @@ func_mode_link () for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" - newlib_search_path="$newlib_search_path $func_stripname_result" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? @@ -4965,12 +6628,12 @@ func_mode_link () # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi - if $opt_duplicate_deps ; then + if $opt_preserve_dup_deps ; then case "$tmp_libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi - tmp_libs="$tmp_libs $deplib" + func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... @@ -4985,7 +6648,7 @@ func_mode_link () # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; - *) temp_rpath="$temp_rpath$absdir:" ;; + *) func_append temp_rpath "$absdir:" ;; esac fi @@ -4997,7 +6660,7 @@ func_mode_link () *) case "$compile_rpath " in *" $absdir "*) ;; - *) compile_rpath="$compile_rpath $absdir" + *) func_append compile_rpath " $absdir" ;; esac ;; esac @@ -5006,7 +6669,7 @@ func_mode_link () *) case "$finalize_rpath " in *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" + *) func_append finalize_rpath " $libdir" ;; esac ;; esac @@ -5029,14 +6692,14 @@ func_mode_link () if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in - *cygwin* | *mingw*) + *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded - notinst_deplibs="$notinst_deplibs $lib" + func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then - notinst_deplibs="$notinst_deplibs $lib" + func_append notinst_deplibs " $lib" need_relink=yes fi ;; @@ -5053,7 +6716,7 @@ func_mode_link () fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then - $ECHO + echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else @@ -5071,7 +6734,7 @@ func_mode_link () *) case "$compile_rpath " in *" $absdir "*) ;; - *) compile_rpath="$compile_rpath $absdir" + *) func_append compile_rpath " $absdir" ;; esac ;; esac @@ -5080,7 +6743,7 @@ func_mode_link () *) case "$finalize_rpath " in *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" + *) func_append finalize_rpath " $libdir" ;; esac ;; esac @@ -5099,7 +6762,7 @@ func_mode_link () elif test -n "$soname_spec"; then # bleh windows case $host in - *cygwin* | mingw*) + *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" @@ -5134,7 +6797,7 @@ func_mode_link () linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" - if test "$linkmode" = prog || test "$mode" != relink; then + if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= @@ -5156,9 +6819,9 @@ func_mode_link () if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then - $ECHO - $ECHO "*** And there doesn't seem to be a static archive available" - $ECHO "*** The link will probably fail, sorry" + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi @@ -5185,12 +6848,12 @@ func_mode_link () test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then - add_dir="-L$dir" + add_dir="-L$absdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) - add_dir="$add_dir -L$inst_prefix_dir$libdir" + func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi @@ -5212,7 +6875,7 @@ func_mode_link () if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; - *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then @@ -5226,13 +6889,13 @@ func_mode_link () test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; - *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi - if test "$linkmode" = prog || test "$mode" = relink; then + if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= @@ -5246,7 +6909,7 @@ func_mode_link () elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; - *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then @@ -5263,7 +6926,7 @@ func_mode_link () if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) - add_dir="$add_dir -L$inst_prefix_dir$libdir" + func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi @@ -5298,21 +6961,21 @@ func_mode_link () # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. - $ECHO + echo $ECHO "*** Warning: This system can not link to static lib archive $lib." - $ECHO "*** I have the capability to make that library automatically link in when" - $ECHO "*** you link to this library. But I can only do this if you have a" - $ECHO "*** shared version of the library, which you do not appear to have." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then - $ECHO "*** But as you try to build a module library, libtool will still create " - $ECHO "*** a static module, that should work as long as the dlopening application" - $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then - $ECHO - $ECHO "*** However, this would only work if libtool was able to extract symbol" - $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" - $ECHO "*** not find such a program. So, this module is probably useless." - $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module @@ -5340,37 +7003,46 @@ func_mode_link () temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; - *) xrpath="$xrpath $temp_xrpath";; + *) func_append xrpath " $temp_xrpath";; esac;; - *) temp_deplibs="$temp_deplibs $libdir";; + *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi - newlib_search_path="$newlib_search_path $absdir" + func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" - if $opt_duplicate_deps ; then + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps ; then case "$tmp_libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi - tmp_libs="$tmp_libs $deplib" + func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do + path= case $deplib in -L*) path="$deplib" ;; *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." - dir="$func_dirname_result" + dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; @@ -5397,8 +7069,8 @@ func_mode_link () if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi - compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" - linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}" + func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi @@ -5431,7 +7103,7 @@ func_mode_link () compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else - compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" @@ -5448,7 +7120,7 @@ func_mode_link () for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; - *) lib_search_path="$lib_search_path $dir" ;; + *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= @@ -5506,10 +7178,10 @@ func_mode_link () -L*) case " $tmp_libs " in *" $deplib "*) ;; - *) tmp_libs="$tmp_libs $deplib" ;; + *) func_append tmp_libs " $deplib" ;; esac ;; - *) tmp_libs="$tmp_libs $deplib" ;; + *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" @@ -5525,7 +7197,7 @@ func_mode_link () ;; esac if test -n "$i" ; then - tmp_libs="$tmp_libs $i" + func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs @@ -5566,7 +7238,7 @@ func_mode_link () # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" - objs="$objs$old_deplibs" + func_append objs "$old_deplibs" ;; lib) @@ -5599,10 +7271,10 @@ func_mode_link () if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else - $ECHO + echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" - libobjs="$libobjs $objs" + func_append libobjs " $objs" fi fi @@ -5661,13 +7333,14 @@ func_mode_link () # which has an extra 1 added just for fun # case $version_type in + # correct linux to gnu/linux during the next big refactor darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; - freebsd-aout|freebsd-elf|sunos) + freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" @@ -5679,6 +7352,9 @@ func_mode_link () revision="$number_minor" lt_irix_increment=no ;; + *) + func_fatal_configuration "$modename: unknown library version type \`$version_type'" + ;; esac ;; no) @@ -5777,7 +7453,7 @@ func_mode_link () versuffix="$major.$revision" ;; - linux) + linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" @@ -5800,7 +7476,7 @@ func_mode_link () done # Make executables depend on our current version. - verstring="$verstring:${current}.0" + func_append verstring ":${current}.0" ;; qnx) @@ -5868,17 +7544,17 @@ func_mode_link () fi func_generate_dlsyms "$libname" "$libname" "yes" - libobjs="$libobjs $symfileobj" + func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= - if test "$mode" != relink; then + if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in - *.$objext) + *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then @@ -5887,7 +7563,7 @@ func_mode_link () continue fi fi - removelist="$removelist $p" + func_append removelist " $p" ;; *) ;; esac @@ -5898,27 +7574,28 @@ func_mode_link () # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then - oldlibs="$oldlibs $output_objdir/$libname.$libext" + func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do - # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` - # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` - # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do - temp_xrpath="$temp_xrpath -R$libdir" + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" ;; + *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then @@ -5932,7 +7609,7 @@ func_mode_link () for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; - *) dlfiles="$dlfiles $lib" ;; + *) func_append dlfiles " $lib" ;; esac done @@ -5942,19 +7619,19 @@ func_mode_link () for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; - *) dlprefiles="$dlprefiles $lib" ;; + *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework - deplibs="$deplibs System.ltframework" + func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. @@ -5971,7 +7648,7 @@ func_mode_link () *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then - deplibs="$deplibs -lc" + func_append deplibs " -lc" fi ;; esac @@ -6020,7 +7697,7 @@ EOF if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $i "*) - newdeplibs="$newdeplibs $i" + func_append newdeplibs " $i" i="" ;; esac @@ -6031,21 +7708,21 @@ EOF set dummy $deplib_matches; shift deplib_match=$1 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then - newdeplibs="$newdeplibs $i" + func_append newdeplibs " $i" else droppeddeps=yes - $ECHO + echo $ECHO "*** Warning: dynamic linker does not accept needed library $i." - $ECHO "*** I have the capability to make that library automatically link in when" - $ECHO "*** you link to this library. But I can only do this if you have a" - $ECHO "*** shared version of the library, which I believe you do not have" - $ECHO "*** because a test_compile did reveal that the linker did not use it for" - $ECHO "*** its dynamic dependency list that programs get resolved with at runtime." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which I believe you do not have" + echo "*** because a test_compile did reveal that the linker did not use it for" + echo "*** its dynamic dependency list that programs get resolved with at runtime." fi fi ;; *) - newdeplibs="$newdeplibs $i" + func_append newdeplibs " $i" ;; esac done @@ -6063,7 +7740,7 @@ EOF if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $i "*) - newdeplibs="$newdeplibs $i" + func_append newdeplibs " $i" i="" ;; esac @@ -6074,29 +7751,29 @@ EOF set dummy $deplib_matches; shift deplib_match=$1 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then - newdeplibs="$newdeplibs $i" + func_append newdeplibs " $i" else droppeddeps=yes - $ECHO + echo $ECHO "*** Warning: dynamic linker does not accept needed library $i." - $ECHO "*** I have the capability to make that library automatically link in when" - $ECHO "*** you link to this library. But I can only do this if you have a" - $ECHO "*** shared version of the library, which you do not appear to have" - $ECHO "*** because a test_compile did reveal that the linker did not use this one" - $ECHO "*** as a dynamic dependency that programs can get resolved with at runtime." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because a test_compile did reveal that the linker did not use this one" + echo "*** as a dynamic dependency that programs can get resolved with at runtime." fi fi else droppeddeps=yes - $ECHO + echo $ECHO "*** Warning! Library $i is needed by this library but I was not able to" - $ECHO "*** make it link in! You will probably need to install it or some" - $ECHO "*** library that it depends on before this library will be fully" - $ECHO "*** functional. Installing it before continuing would be even better." + echo "*** make it link in! You will probably need to install it or some" + echo "*** library that it depends on before this library will be fully" + echo "*** functional. Installing it before continuing would be even better." fi ;; *) - newdeplibs="$newdeplibs $i" + func_append newdeplibs " $i" ;; esac done @@ -6113,15 +7790,27 @@ EOF if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) - newdeplibs="$newdeplibs $a_deplib" + func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` + if test -n "$file_magic_glob"; then + libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob` + else + libnameglob=$libname + fi + test "$want_nocaseglob" = yes && nocaseglob=`shopt -p nocaseglob` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + if test "$want_nocaseglob" = yes; then + shopt -s nocaseglob + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | @@ -6138,13 +7827,13 @@ EOF potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then - newdeplibs="$newdeplibs $a_deplib" + func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi @@ -6153,12 +7842,12 @@ EOF fi if test -n "$a_deplib" ; then droppeddeps=yes - $ECHO + echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - $ECHO "*** I have the capability to make that library automatically link in when" - $ECHO "*** you link to this library. But I can only do this if you have a" - $ECHO "*** shared version of the library, which you do not appear to have" - $ECHO "*** because I did check the linker path looking for a file starting" + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else @@ -6169,7 +7858,7 @@ EOF ;; *) # Add a -L argument. - newdeplibs="$newdeplibs $a_deplib" + func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. @@ -6185,7 +7874,7 @@ EOF if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) - newdeplibs="$newdeplibs $a_deplib" + func_append newdeplibs " $a_deplib" a_deplib="" ;; esac @@ -6196,9 +7885,9 @@ EOF potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test - if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then - newdeplibs="$newdeplibs $a_deplib" + func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi @@ -6207,12 +7896,12 @@ EOF fi if test -n "$a_deplib" ; then droppeddeps=yes - $ECHO + echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - $ECHO "*** I have the capability to make that library automatically link in when" - $ECHO "*** you link to this library. But I can only do this if you have a" - $ECHO "*** shared version of the library, which you do not appear to have" - $ECHO "*** because I did check the linker path looking for a file starting" + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else @@ -6223,32 +7912,32 @@ EOF ;; *) # Add a -L argument. - newdeplibs="$newdeplibs $a_deplib" + func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" - tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ - -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi - if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | - $GREP . >/dev/null; then - $ECHO + case $tmp_deplibs in + *[!\ \ ]*) + echo if test "X$deplibs_check_method" = "Xnone"; then - $ECHO "*** Warning: inter-library dependencies are not supported in this platform." + echo "*** Warning: inter-library dependencies are not supported in this platform." else - $ECHO "*** Warning: inter-library dependencies are not known to be supported." + echo "*** Warning: inter-library dependencies are not known to be supported." fi - $ECHO "*** All declared inter-library dependencies are being dropped." + echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes - fi + ;; + esac ;; esac versuffix=$versuffix_save @@ -6260,23 +7949,23 @@ EOF case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework - newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then - $ECHO - $ECHO "*** Warning: libtool could not satisfy all declared inter-library" + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" - $ECHO "*** a static module, that should work as long as the dlopening" - $ECHO "*** application is linked with the -dlopen flag." + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then - $ECHO - $ECHO "*** However, this would only work if libtool was able to extract symbol" - $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" - $ECHO "*** not find such a program. So, this module is probably useless." - $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" @@ -6286,16 +7975,16 @@ EOF build_libtool_libs=no fi else - $ECHO "*** The inter-library dependencies that have been dropped here will be" - $ECHO "*** automatically added whenever a program is linked with this library" - $ECHO "*** or is declared to -dlopen it." + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then - $ECHO - $ECHO "*** Since this library must not contain undefined symbols," - $ECHO "*** because either the platform does not support them or" - $ECHO "*** it was explicitly requested with -no-undefined," - $ECHO "*** libtool will only create a static version of it." + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module @@ -6312,9 +8001,9 @@ EOF # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) - newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` - new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` - deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac @@ -6327,7 +8016,7 @@ EOF *) case " $deplibs " in *" -L$path/$objdir "*) - new_libs="$new_libs -L$path/$objdir" ;; + func_append new_libs " -L$path/$objdir" ;; esac ;; esac @@ -6337,10 +8026,10 @@ EOF -L*) case " $new_libs " in *" $deplib "*) ;; - *) new_libs="$new_libs $deplib" ;; + *) func_append new_libs " $deplib" ;; esac ;; - *) new_libs="$new_libs $deplib" ;; + *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" @@ -6352,15 +8041,22 @@ EOF # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then + # Remove ${wl} instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" - test "$mode" != relink && rpath="$compile_rpath$rpath" + test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else @@ -6369,18 +8065,18 @@ EOF *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" - dep_rpath="$dep_rpath $flag" + func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; - *) perm_rpath="$perm_rpath $libdir" ;; + *) func_append perm_rpath " $libdir" ;; esac fi done @@ -6388,17 +8084,13 @@ EOF if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" - if test -n "$hardcode_libdir_flag_spec_ld"; then - eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" - else - eval dep_rpath=\"$hardcode_libdir_flag_spec\" - fi + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do - rpath="$rpath$dir:" + func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi @@ -6406,7 +8098,7 @@ EOF fi shlibpath="$finalize_shlibpath" - test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi @@ -6432,23 +8124,23 @@ EOF linknames= for link do - linknames="$linknames $link" + func_append linknames " $link" done # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" - delfiles="$delfiles $export_symbols" + func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in - cygwin* | mingw*) + cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then @@ -6474,13 +8166,45 @@ EOF $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do + for cmd1 in $cmds; do IFS="$save_ifs" - eval cmd=\"$cmd\" - func_len " $cmd" - len=$func_len_result - if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test "$try_normal_branch" = yes \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=${output_objdir}/${output_la}.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. @@ -6502,7 +8226,7 @@ EOF if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" - $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then @@ -6514,7 +8238,7 @@ EOF # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi @@ -6524,7 +8248,7 @@ EOF case " $convenience " in *" $test_deplib "*) ;; *) - tmp_deplibs="$tmp_deplibs $test_deplib" + func_append tmp_deplibs " $test_deplib" ;; esac done @@ -6544,21 +8268,21 @@ EOF test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" - generated="$generated $gentop" + func_append generated " $gentop" func_extract_archives $gentop $convenience - libobjs="$libobjs $func_extract_archives_result" + func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" - linker_flags="$linker_flags $flag" + func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking - if test "$mode" = relink; then + if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi @@ -6603,7 +8327,8 @@ EOF save_libobjs=$libobjs fi save_output=$output - output_la=`$ECHO "X$output" | $Xsed -e "$basename"` + func_basename "$output" + output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. @@ -6616,13 +8341,16 @@ EOF if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" - $ECHO 'INPUT (' > $output + echo 'INPUT (' > $output for obj in $save_libobjs do - $ECHO "$obj" >> $output + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output done - $ECHO ')' >> $output - delfiles="$delfiles $output" + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" @@ -6636,10 +8364,12 @@ EOF fi for obj do - $ECHO "$obj" >> $output + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output done - delfiles="$delfiles $output" - output=$firstobj\"$file_list_spec$output\" + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." @@ -6663,17 +8393,19 @@ EOF # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. - eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. - eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext - objlist=$obj + objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result @@ -6683,11 +8415,12 @@ EOF # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi - delfiles="$delfiles $output" + func_append delfiles " $output" else output= @@ -6721,7 +8454,7 @@ EOF lt_exit=$? # Restore the uninstalled library and exit - if test "$mode" = relink; then + if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) @@ -6742,7 +8475,7 @@ EOF if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" - $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then @@ -6754,7 +8487,7 @@ EOF # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi @@ -6795,10 +8528,10 @@ EOF # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" - generated="$generated $gentop" + func_append generated " $gentop" func_extract_archives $gentop $dlprefiles - libobjs="$libobjs $func_extract_archives_result" + func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi @@ -6814,7 +8547,7 @@ EOF lt_exit=$? # Restore the uninstalled library and exit - if test "$mode" = relink; then + if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) @@ -6826,7 +8559,7 @@ EOF IFS="$save_ifs" # Restore the uninstalled library and exit - if test "$mode" = relink; then + if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then @@ -6907,18 +8640,21 @@ EOF if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` + reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" - generated="$generated $gentop" + func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi + # If we're not building shared, we need to use non_pic_objs + test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + # Create the old-style object. - reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' @@ -6978,8 +8714,8 @@ EOF case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework - compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` - finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac @@ -6990,14 +8726,14 @@ EOF if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) - compile_command="$compile_command ${wl}-bind_at_load" - finalize_command="$finalize_command ${wl}-bind_at_load" + func_append compile_command " ${wl}-bind_at_load" + func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" - compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` - finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac @@ -7011,7 +8747,7 @@ EOF *) case " $compile_deplibs " in *" -L$path/$objdir "*) - new_libs="$new_libs -L$path/$objdir" ;; + func_append new_libs " -L$path/$objdir" ;; esac ;; esac @@ -7021,17 +8757,17 @@ EOF -L*) case " $new_libs " in *" $deplib "*) ;; - *) new_libs="$new_libs $deplib" ;; + *) func_append new_libs " $deplib" ;; esac ;; - *) new_libs="$new_libs $deplib" ;; + *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" - compile_command="$compile_command $compile_deplibs" - finalize_command="$finalize_command $finalize_deplibs" + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. @@ -7039,7 +8775,7 @@ EOF # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" ;; + *) func_append finalize_rpath " $libdir" ;; esac done fi @@ -7058,30 +8794,32 @@ EOF *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" - rpath="$rpath $flag" + func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; - *) perm_rpath="$perm_rpath $libdir" ;; + *) func_append perm_rpath " $libdir" ;; esac fi case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; - *) dllsearchpath="$dllsearchpath:$libdir";; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; - *) dllsearchpath="$dllsearchpath:$testbindir";; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; esac ;; esac @@ -7107,18 +8845,18 @@ EOF *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" - rpath="$rpath $flag" + func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; - *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + *) func_append finalize_perm_rpath " $libdir" ;; esac fi done @@ -7132,8 +8870,8 @@ EOF if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. - compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" @@ -7145,6 +8883,10 @@ EOF wrappers_required=yes case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=no + ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no @@ -7158,13 +8900,19 @@ EOF esac if test "$wrappers_required" = no; then # Replace the output file specification. - compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' @@ -7187,7 +8935,7 @@ EOF # We should set the runpath_var. rpath= for dir in $perm_rpath; do - rpath="$rpath$dir:" + func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi @@ -7195,7 +8943,7 @@ EOF # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do - rpath="$rpath$dir:" + func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi @@ -7205,11 +8953,18 @@ EOF # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. - link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + exit $EXIT_SUCCESS fi @@ -7224,7 +8979,7 @@ EOF if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then - relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= @@ -7236,13 +8991,19 @@ EOF fi # Replace the output file specification. - link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + # Now create the wrapper script. func_verbose "creating $output" @@ -7260,18 +9021,7 @@ EOF fi done relink_command="(cd `pwd`; $relink_command)" - relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` - fi - - # Quote $ECHO for shipping. - if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then - case $progpath in - [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; - *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; - esac - qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` - else - qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. @@ -7302,11 +9052,10 @@ EOF func_emit_cwrapperexe_src > $cwrappersource - # we should really use a build-platform specific compiler - # here, but OTOH, the wrappers (shell script and this C one) - # are only useful if you want to execute the "real" binary. - # Since the "real" binary is built for $host, then this - # wrapper might as well be built for $host, too. + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper @@ -7352,7 +9101,7 @@ EOF else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then - oldobjs="$oldobjs $symfileobj" + func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" @@ -7360,10 +9109,10 @@ EOF if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" - generated="$generated $gentop" + func_append generated " $gentop" func_extract_archives $gentop $addlibs - oldobjs="$oldobjs $func_extract_archives_result" + func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. @@ -7374,10 +9123,10 @@ EOF # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" - generated="$generated $gentop" + func_append generated " $gentop" func_extract_archives $gentop $dlprefiles - oldobjs="$oldobjs $func_extract_archives_result" + func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have @@ -7393,9 +9142,9 @@ EOF done | sort | sort -uc >/dev/null 2>&1); then : else - $ECHO "copying selected object files to avoid basename conflicts..." + echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" - generated="$generated $gentop" + func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= @@ -7419,18 +9168,30 @@ EOF esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" - oldobjs="$oldobjs $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" ;; - *) oldobjs="$oldobjs $obj" ;; + *) func_append oldobjs " $obj" ;; esac done fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." @@ -7504,7 +9265,7 @@ EOF done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi @@ -7524,12 +9285,23 @@ EOF *.la) func_basename "$deplib" name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + func_resolve_sysroot "$deplib" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" - newdependency_libs="$newdependency_libs $libdir/$name" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" ;; - *) newdependency_libs="$newdependency_libs $deplib" ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" @@ -7543,9 +9315,9 @@ EOF eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" - newdlfiles="$newdlfiles $libdir/$name" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; - *) newdlfiles="$newdlfiles $lib" ;; + *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" @@ -7562,7 +9334,7 @@ EOF eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" - newdlprefiles="$newdlprefiles $libdir/$name" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done @@ -7574,7 +9346,7 @@ EOF [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac - newdlfiles="$newdlfiles $abs" + func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= @@ -7583,15 +9355,33 @@ EOF [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac - newdlprefiles="$newdlprefiles $abs" + func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in - *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test "x$bindir" != x ; + then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; esac $ECHO > $output "\ # $outputname - a libtool library file @@ -7650,7 +9440,7 @@ relink_command=\"$relink_command\"" exit $EXIT_SUCCESS } -{ test "$mode" = link || test "$mode" = relink; } && +{ test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} @@ -7670,9 +9460,9 @@ func_mode_uninstall () for arg do case $arg in - -f) RM="$RM $arg"; rmforce=yes ;; - -*) RM="$RM $arg" ;; - *) files="$files $arg" ;; + -f) func_append RM " $arg"; rmforce=yes ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; esac done @@ -7681,24 +9471,23 @@ func_mode_uninstall () rmdirs= - origobjdir="$objdir" for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then - objdir="$origobjdir" + odir="$objdir" else - objdir="$dir/$origobjdir" + odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" - test "$mode" = uninstall && objdir="$dir" + test "$opt_mode" = uninstall && odir="$dir" - # Remember objdir for removal later, being careful to avoid duplicates - if test "$mode" = clean; then + # Remember odir for removal later, being careful to avoid duplicates + if test "$opt_mode" = clean; then case " $rmdirs " in - *" $objdir "*) ;; - *) rmdirs="$rmdirs $objdir" ;; + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; esac fi @@ -7724,18 +9513,17 @@ func_mode_uninstall () # Delete the libtool libraries and symlinks. for n in $library_names; do - rmfiles="$rmfiles $objdir/$n" + func_append rmfiles " $odir/$n" done - test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + test -n "$old_library" && func_append rmfiles " $odir/$old_library" - case "$mode" in + case "$opt_mode" in clean) - case " $library_names " in - # " " in the beginning catches empty $dlname + case " $library_names " in *" $dlname "*) ;; - *) rmfiles="$rmfiles $objdir/$dlname" ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac - test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then @@ -7763,19 +9551,19 @@ func_mode_uninstall () # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then - rmfiles="$rmfiles $dir/$pic_object" + func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then - rmfiles="$rmfiles $dir/$non_pic_object" + func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) - if test "$mode" = clean ; then + if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) @@ -7785,7 +9573,7 @@ func_mode_uninstall () noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe - rmfiles="$rmfiles $file" + func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. @@ -7794,7 +9582,7 @@ func_mode_uninstall () func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result - rmfiles="$rmfiles $func_ltwrapper_scriptname_result" + func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename @@ -7802,12 +9590,12 @@ func_mode_uninstall () # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles - rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + func_append rmfiles " $odir/$name $odir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then - rmfiles="$rmfiles $objdir/lt-$name" + func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name" ; then - rmfiles="$rmfiles $objdir/lt-${noexename}.c" + func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi @@ -7815,7 +9603,6 @@ func_mode_uninstall () esac func_show_eval "$RM $rmfiles" 'exit_status=1' done - objdir="$origobjdir" # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do @@ -7827,16 +9614,16 @@ func_mode_uninstall () exit $exit_status } -{ test "$mode" = uninstall || test "$mode" = clean; } && +{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} -test -z "$mode" && { +test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ - func_fatal_help "invalid operation mode \`$mode'" + func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" diff --git a/m4/acx_pthread.m4 b/m4/acx_pthread.m4 index 2cf20de..89d42c7 100644 --- a/m4/acx_pthread.m4 +++ b/m4/acx_pthread.m4 @@ -340,6 +340,40 @@ if test "x$acx_pthread_ok" = xyes; then acx_pthread_ok=no fi + AC_MSG_CHECKING([whether what we have so far is sufficient with -nostdlib]) + CFLAGS="-nostdlib $CFLAGS" + # we need c with nostdlib + LIBS="$LIBS -lc" + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [done=yes],[done=no]) + + if test "x$done" = xyes; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + + if test x"$done" = xno; then + AC_MSG_CHECKING([whether -lpthread saves the day]) + LIBS="-lpthread $LIBS" + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [done=yes],[done=no]) + + if test "x$done" = xyes; then + AC_MSG_RESULT([yes]) + PTHREAD_LIBS="$PTHREAD_LIBS -lpthread" + else + AC_MSG_RESULT([no]) + AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries and -nostdlib]) + fi + fi + CFLAGS="$save_CFLAGS" LIBS="$save_LIBS" CC="$save_CC" diff --git a/m4/libtool.m4 b/m4/libtool.m4 index 4ceb7f1..828104c 100644 --- a/m4/libtool.m4 +++ b/m4/libtool.m4 @@ -1,7 +1,8 @@ # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives @@ -10,7 +11,8 @@ m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. @@ -37,7 +39,7 @@ m4_define([_LT_COPYING], [dnl # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) -# serial 56 LT_INIT +# serial 57 LT_INIT # LT_PREREQ(VERSION) @@ -66,6 +68,7 @@ esac # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl @@ -82,6 +85,8 @@ AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) @@ -118,7 +123,7 @@ m4_defun([_LT_CC_BASENAME], *) break;; esac done -cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) @@ -138,6 +143,11 @@ m4_defun([_LT_FILEUTILS_DEFAULTS], m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl @@ -160,10 +170,13 @@ _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our @@ -179,7 +192,6 @@ fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl -_LT_PROG_ECHO_BACKSLASH case $host_os in aix3*) @@ -193,23 +205,6 @@ aix3*) ;; esac -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([["`\\]]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - # Global variables: ofile=libtool can_build_shared=yes @@ -250,6 +245,28 @@ _LT_CONFIG_COMMANDS ])# _LT_SETUP +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' @@ -380,12 +397,12 @@ m4_define([lt_decl_dquote_varnames], # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], -[_$0(m4_quote(m4_default([$1], [[, ]])), - m4_quote(m4_if([$2], [], - m4_quote(lt_decl_tag_varnames), - m4_quote(m4_shift($@)))), - m4_split(m4_normalize(m4_quote(_LT_TAGS))))]) -m4_define([_lt_decl_varnames_tagged], [lt_combine([$1], [$2], [_], $3)]) +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) @@ -408,7 +425,7 @@ m4_define([_lt_decl_all_varnames], # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], -[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`']) +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS @@ -418,7 +435,7 @@ m4_define([_LT_CONFIG_STATUS_DECLARE], # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # -# ='`$ECHO "X$" | $Xsed -e "$delay_single_quote_subst"`' +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) @@ -517,12 +534,20 @@ LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -533,9 +558,9 @@ done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -543,16 +568,38 @@ for var in lt_decl_all_varnames([[ \ esac done -# Fix-up fallback echo if it was mangled by the above quoting rules. -case \$lt_ECHO in -*'\\\[$]0 --fallback-echo"')dnl " - lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\` - ;; -esac - _LT_OUTPUT_LIBTOOL_INIT ]) +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# `#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test $lt_write_fail = 0 && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- @@ -562,20 +609,11 @@ _LT_OUTPUT_LIBTOOL_INIT AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) -cat >"$CONFIG_LT" <<_LTEOF -#! $SHELL -# Generated by $as_me. -# Run this file to recreate a libtool stub with the current configuration. - -lt_cl_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_LTEOF +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF -AS_SHELL_SANITIZE -_AS_PREPARE - -exec AS_MESSAGE_FD>&1 +lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo @@ -601,7 +639,7 @@ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. -Copyright (C) 2008 Free Software Foundation, Inc. +Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." @@ -646,15 +684,13 @@ chmod +x "$CONFIG_LT" # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. -if test "$no_create" != yes; then - lt_cl_success=: - test "$silent" = yes && - lt_config_lt_args="$lt_config_lt_args --quiet" - exec AS_MESSAGE_LOG_FD>/dev/null - $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false - exec AS_MESSAGE_LOG_FD>>config.log - $lt_cl_success || AS_EXIT(1) -fi +lt_cl_success=: +test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT @@ -717,15 +753,12 @@ _LT_EOF # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? - sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) - _LT_PROG_XSI_SHELLFNS + _LT_PROG_REPLACE_SHELLFNS - sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || + mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], @@ -770,6 +803,7 @@ AC_DEFUN([LT_LANG], m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], @@ -791,6 +825,31 @@ m4_defun([_LT_LANG], ])# _LT_LANG +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], @@ -821,6 +880,10 @@ AC_PROVIDE_IFELSE([AC_PROG_GCJ], m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) @@ -831,11 +894,13 @@ AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER @@ -921,7 +986,13 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? - if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD @@ -929,6 +1000,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ rm -rf libconftest.dylib* rm -f conftest.* fi]) + AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no @@ -940,15 +1012,43 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - darwin*) # darwin 5.x on + darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment - # target defaults to 10.4. Don't you love it? + # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; @@ -967,7 +1067,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi - if test "$DSYMUTIL" != ":"; then + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= @@ -977,8 +1077,8 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ ]) -# _LT_DARWIN_LINKER_FEATURES -# -------------------------- +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ @@ -987,11 +1087,21 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES], _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_TAGVAR(whole_archive_flag_spec, $1)='' + if test "$lt_cv_ld_force_load" = "yes"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" - if test "$GCC" = "yes"; then - output_verbose_link_cmd=echo + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" @@ -1007,203 +1117,142 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES], fi ]) -# _LT_SYS_MODULE_PATH_AIX -# ----------------------- +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl -AC_LINK_IFELSE(AC_LANG_PROGRAM,[ -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi],[]) -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], -[ifdef([AC_DIVERSION_NOTICE], - [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], - [AC_DIVERT_PUSH(NOTICE)]) -$1 -AC_DIVERT_POP -])# _LT_SHELL_INIT +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + # _LT_PROG_ECHO_BACKSLASH # ----------------------- -# Add some code to the start of the generated configure script which -# will find an echo command which doesn't interpret backslashes. +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script which will find a shell with a builtin +# printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], -[_LT_SHELL_INIT([ -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} - -case X$lt_ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` - ;; -esac - -ECHO=${lt_ECHO-echo} -if test "X[$]1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X[$]1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then - # Yippee, $ECHO works! - : +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' else - # Restart under the correct shell. - exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} -fi - -if test "X[$]1" = X--fallback-echo; then - # used as fallback echo - shift - cat <<_LT_EOF -[$]* -_LT_EOF - exit 0 + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' fi -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -if test -z "$lt_ECHO"; then - if test "X${echo_test_string+set}" != Xset; then - # find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if { echo_test_string=`eval $cmd`; } 2>/dev/null && - { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null - then - break - fi - done - fi - - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : - else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$ECHO" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - ECHO='print -r' - elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} - else - # Try using printf. - ECHO='printf %s\n' - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - ECHO="$CONFIG_SHELL [$]0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$CONFIG_SHELL [$]0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do - if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null - then - break - fi - prev="$cmd" - done +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} - if test "$prev" != 'sed 50q "[$]0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} - else - # Oops. We lost completely, so just stick with echo. - ECHO=echo - fi - fi - fi - fi - fi -fi +case "$ECHO" in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -lt_ECHO=$ECHO -if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then - lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" -fi +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) -AC_SUBST(lt_ECHO) -]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) -_LT_DECL([], [ECHO], [1], - [An echo program that does not interpret backslashes]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[ --with-sysroot[=DIR] Search for dependent libraries within DIR + (or the compiler's sysroot if not specified).], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and in which our libraries should be installed.])]) + # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], @@ -1232,7 +1281,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '[#]line __oline__ "configure"' > conftest.$ac_ext + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in @@ -1325,14 +1374,27 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) CFLAGS="$SAVE_CFLAGS" fi ;; -sparc*-*solaris*) +*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in - yes*) LD="${LD-ld} -m elf64_sparc" ;; + yes*) + case $host in + i?86-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD="${LD-ld}_sol2" + fi + ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" @@ -1350,14 +1412,47 @@ need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], -[AC_CHECK_TOOL(AR, ar, false) -test -z "$AR" && AR=ar -test -z "$AR_FLAGS" && AR_FLAGS=cru -_LT_DECL([], [AR], [1], [The archiver]) -_LT_DECL([], [AR_FLAGS], [1]) +[_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: @@ -1376,18 +1471,27 @@ old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE @@ -1412,15 +1516,15 @@ AC_CACHE_CHECK([$1], [$2], -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes @@ -1460,7 +1564,7 @@ AC_CACHE_CHECK([$1], [$2], if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD - $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes @@ -1512,7 +1616,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl lt_cv_sys_max_cmd_len=-1; ;; - cygwin* | mingw*) + cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, @@ -1523,6 +1627,11 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl lt_cv_sys_max_cmd_len=8192; ;; + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. @@ -1548,6 +1657,11 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl lt_cv_sys_max_cmd_len=196608 ;; + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not @@ -1587,8 +1701,8 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ - = "XX$teststring$teststring"; } >/dev/null 2>&1 && + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` @@ -1639,7 +1753,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -[#line __oline__ "configure" +[#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -1680,11 +1794,13 @@ else # endif #endif -#ifdef __cplusplus -extern "C" void exit (int); +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); #endif -void fnord() { int i=42;} +int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); @@ -1693,13 +1809,17 @@ int main () if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } /* dlclose (self); */ } else puts (dlerror ()); - exit (status); + return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then @@ -1738,7 +1858,7 @@ else lt_cv_dlopen_self=yes ;; - mingw* | pw32*) + mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; @@ -1869,16 +1989,16 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes @@ -2035,7 +2155,9 @@ m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ @@ -2044,16 +2166,23 @@ if test "$GCC" = yes; then darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` - else - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= @@ -2066,7 +2195,7 @@ if test "$GCC" = yes; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done - lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; @@ -2086,7 +2215,13 @@ BEGIN {RS=" "; FS="/|\n";} { if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` - sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) @@ -2112,7 +2247,7 @@ need_version=unknown case $host_os in aix3*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH @@ -2121,7 +2256,7 @@ aix3*) ;; aix[[4-9]]*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes @@ -2174,7 +2309,7 @@ amigaos*) m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; @@ -2186,7 +2321,7 @@ beos*) ;; bsdi[[45]]*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' @@ -2199,14 +2334,15 @@ bsdi[[45]]*) # libtool to hard-code these into programs ;; -cygwin* | mingw* | pw32*) +cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) + case $GCC,$cc_basename in + yes,*) + # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ @@ -2227,36 +2363,83 @@ cygwin* | mingw* | pw32*) cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; - mingw*) + mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' ;; *) + # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' ;; esac - dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; @@ -2277,7 +2460,7 @@ m4_if([$1], [],[ ;; dgux*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' @@ -2285,10 +2468,6 @@ dgux*) shlibpath_var=LD_LIBRARY_PATH ;; -freebsd1*) - dynamic_linker=no - ;; - freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. @@ -2296,7 +2475,7 @@ freebsd* | dragonfly*) objformat=`/usr/bin/objformat` else case $host_os in - freebsd[[123]]*) objformat=aout ;; + freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi @@ -2314,7 +2493,7 @@ freebsd* | dragonfly*) esac shlibpath_var=LD_LIBRARY_PATH case $host_os in - freebsd2*) + freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) @@ -2334,12 +2513,26 @@ freebsd* | dragonfly*) ;; gnu*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -2385,12 +2578,14 @@ hpux9* | hpux10* | hpux11*) soname_spec='${libname}${release}${shared_ext}$major' ;; esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 ;; interix[[3-9]]*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' @@ -2406,7 +2601,7 @@ irix5* | irix6* | nonstopux*) nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; @@ -2443,9 +2638,9 @@ linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; -# This must be Linux ELF. -linux* | k*bsd*-gnu) - version_type=linux +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -2453,16 +2648,21 @@ linux* | k*bsd*-gnu) finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no + # Some binutils ld are patched to set DT_RUNPATH - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ - LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" - AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], - [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], - [shlibpath_overrides_runpath=yes])]) - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install @@ -2471,7 +2671,7 @@ linux* | k*bsd*-gnu) # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi @@ -2484,6 +2684,18 @@ linux* | k*bsd*-gnu) dynamic_linker='GNU/Linux ld.so' ;; +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + netbsd*) version_type=sunos need_lib_prefix=no @@ -2503,7 +2715,7 @@ netbsd*) ;; newsos6) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes @@ -2572,7 +2784,7 @@ rdos*) ;; solaris*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -2597,7 +2809,7 @@ sunos4*) ;; sysv4 | sysv4.3*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH @@ -2621,7 +2833,7 @@ sysv4 | sysv4.3*) sysv4*MP*) if test -d /usr/nec ;then - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH @@ -2652,17 +2864,17 @@ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_name_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH @@ -2679,7 +2891,7 @@ variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi - + if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi @@ -2704,6 +2916,8 @@ _LT_DECL([], [library_names_spec], [1], The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], @@ -2816,6 +3030,7 @@ AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], @@ -2937,6 +3152,11 @@ case $reload_flag in esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' @@ -2945,8 +3165,8 @@ case $host_os in fi ;; esac -_LT_DECL([], [reload_flag], [1], [How to create reloadable object files])dnl -_LT_DECL([], [reload_cmds], [2])dnl +_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl +_LT_TAGDECL([], [reload_cmds], [2])dnl ])# _LT_CMD_RELOAD @@ -2956,6 +3176,7 @@ _LT_DECL([], [reload_cmds], [2])dnl # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' @@ -2997,15 +3218,23 @@ mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. - if ( file / ) >/dev/null 2>&1; then + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; @@ -3030,6 +3259,10 @@ gnu*) lt_cv_deplibs_check_method=pass_all ;; +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in @@ -3038,11 +3271,11 @@ hpux10.20* | hpux11*) lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) - [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac @@ -3063,12 +3296,12 @@ irix5* | irix6* | nonstopux*) lt_cv_deplibs_check_method=pass_all ;; -# This must be Linux ELF. -linux* | k*bsd*-gnu) +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; -netbsd*) +netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else @@ -3142,6 +3375,21 @@ tpf*) ;; esac ]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown @@ -3149,7 +3397,11 @@ test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], - [Command to use when deplibs_check_method == "file_magic"]) + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD @@ -3206,7 +3458,19 @@ if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. - AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :) + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" @@ -3219,13 +3483,13 @@ _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD) + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -3240,6 +3504,67 @@ dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + # LT_LIB_M # -------- @@ -3248,7 +3573,7 @@ AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in -*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) @@ -3276,7 +3601,12 @@ m4_defun([_LT_COMPILER_NO_RTTI], _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, @@ -3293,6 +3623,7 @@ _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl @@ -3317,7 +3648,7 @@ case $host_os in aix*) symcode='[[BCDT]]' ;; -cygwin* | mingw* | pw32*) +cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) @@ -3360,8 +3691,8 @@ esac lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -3385,6 +3716,7 @@ for ac_symprfx in "" "_"; do # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ @@ -3397,6 +3729,7 @@ for ac_symprfx in "" "_"; do else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no @@ -3418,7 +3751,7 @@ _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm - if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" @@ -3430,6 +3763,18 @@ _LT_EOF if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + #ifdef __cplusplus extern "C" { #endif @@ -3441,7 +3786,7 @@ _LT_EOF cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ -const struct { +LT@&t@_DLSYM_CONST struct { const char *name; void *address; } @@ -3467,15 +3812,15 @@ static const void *lt_preloaded_setup() { _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext - lt_save_LIBS="$LIBS" - lt_save_CFLAGS="$CFLAGS" + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi - LIBS="$lt_save_LIBS" - CFLAGS="$lt_save_CFLAGS" + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi @@ -3508,6 +3853,13 @@ else AC_MSG_RESULT(ok) fi +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], @@ -3518,6 +3870,8 @@ _LT_DECL([global_symbol_to_c_name_address], _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS @@ -3529,7 +3883,6 @@ _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= -AC_MSG_CHECKING([for $compiler option to produce PIC]) m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then @@ -3563,7 +3916,7 @@ m4_if([$1], [CXX], [ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; - mingw* | cygwin* | os2* | pw32*) + mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style @@ -3580,6 +3933,11 @@ m4_if([$1], [CXX], [ # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. @@ -3590,10 +3948,11 @@ m4_if([$1], [CXX], [ fi ;; hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. case $host_cpu in - hppa*64*|ia64*) + hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' @@ -3628,6 +3987,12 @@ m4_if([$1], [CXX], [ ;; esac ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; dgux*) case $cc_basename in ec++*) @@ -3684,19 +4049,26 @@ m4_if([$1], [CXX], [ ;; esac ;; - linux* | k*bsd*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; - icpc* | ecpc* ) - # Intel C++ + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' @@ -3710,8 +4082,8 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; - xlc* | xlC*) - # IBM XL 8.0 on PPC + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' @@ -3741,7 +4113,7 @@ m4_if([$1], [CXX], [ ;; esac ;; - netbsd*) + netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise @@ -3773,7 +4145,7 @@ m4_if([$1], [CXX], [ ;; solaris*) case $cc_basename in - CC*) + CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' @@ -3862,7 +4234,7 @@ m4_if([$1], [CXX], [ # PIC is the default for these OSes. ;; - mingw* | cygwin* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style @@ -3877,11 +4249,18 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. case $host_cpu in - hppa*64*|ia64*) + hppa*64*) # +Z the default ;; *) @@ -3918,6 +4297,15 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in @@ -3931,7 +4319,7 @@ m4_if([$1], [CXX], [ fi ;; - mingw* | cygwin* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], @@ -3960,14 +4348,34 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; - linux* | k*bsd*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in - icc* | ecc* | ifort*) + # old Intel for x86_64 which still supported -KPIC. + ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; - pgcc* | pgf77* | pgf90* | pgf95*) + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' @@ -3979,25 +4387,40 @@ m4_if([$1], [CXX], [ # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; - xl*) - # IBM XL C 8.0/Fortran 10.1 on PPC + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; - *Sun\ F*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; esac ;; @@ -4029,7 +4452,7 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in - f77* | f90* | f95*) + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; @@ -4086,9 +4509,11 @@ case $host_os in _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac -AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) -_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], - [How to pass a linker flag through the compiler]) + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. @@ -4107,6 +4532,8 @@ fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # @@ -4127,6 +4554,7 @@ _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl @@ -4135,27 +4563,40 @@ m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" - ;; - cygwin* | mingw*) - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' - ;; + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; + ;; esac - _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= @@ -4170,7 +4611,6 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported @@ -4200,7 +4640,7 @@ dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. @@ -4215,10 +4655,39 @@ dnl Note also adjust exclude_expsyms for C++ above. openbsd*) with_gnu_ld=no ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' @@ -4236,6 +4705,7 @@ dnl Note also adjust exclude_expsyms for C++ above. fi supports_anon_versioning=no case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... @@ -4251,11 +4721,12 @@ dnl Note also adjust exclude_expsyms for C++ above. _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 -*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. _LT_EOF fi @@ -4287,14 +4758,16 @@ _LT_EOF fi ;; - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' @@ -4312,6 +4785,11 @@ _LT_EOF fi ;; + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no @@ -4327,7 +4805,7 @@ _LT_EOF _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; - gnu* | linux* | tpf* | k*bsd*-gnu) + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in @@ -4337,15 +4815,16 @@ _LT_EOF if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then - tmp_addflag= + tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -4353,13 +4832,20 @@ _LT_EOF tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; - xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 @@ -4375,17 +4861,16 @@ _LT_EOF fi case $cc_basename in - xlf*) + xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' - _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -4394,13 +4879,13 @@ _LT_EOF fi ;; - netbsd*) + netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; @@ -4418,8 +4903,8 @@ _LT_EOF _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -4465,8 +4950,8 @@ _LT_EOF *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -4506,8 +4991,10 @@ _LT_EOF else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi @@ -4569,6 +5056,7 @@ _LT_EOF if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi + _LT_TAGVAR(link_all_deplibs, $1)=no else # not using gcc if test "$host_cpu" = ia64; then @@ -4584,6 +5072,7 @@ _LT_EOF fi fi + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes @@ -4593,9 +5082,9 @@ _LT_EOF _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. - _LT_SYS_MODULE_PATH_AIX + _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' @@ -4604,14 +5093,19 @@ _LT_EOF else # Determine the default libpath from the value encoded in an # empty executable. - _LT_SYS_MODULE_PATH_AIX + _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' @@ -4638,25 +5132,69 @@ _LT_EOF _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' - # FIXME: Should let the user specify the lib program. - _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' - _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac ;; darwin* | rhapsody*) @@ -4669,10 +5207,6 @@ _LT_EOF _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; - freebsd1*) - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little @@ -4685,7 +5219,7 @@ _LT_EOF ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) + freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes @@ -4694,7 +5228,7 @@ _LT_EOF # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no @@ -4702,7 +5236,7 @@ _LT_EOF hpux9*) if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi @@ -4717,14 +5251,13 @@ _LT_EOF ;; hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes @@ -4736,16 +5269,16 @@ _LT_EOF ;; hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then + if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else @@ -4757,7 +5290,14 @@ _LT_EOF _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi @@ -4785,19 +5325,34 @@ _LT_EOF irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" - AC_LINK_IFELSE(int foo(void) {}, - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' - ) - LDFLAGS="$save_LDFLAGS" + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS="$save_LDFLAGS"]) + if test "$lt_cv_irix_exported_symbol" = yes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' @@ -4806,7 +5361,7 @@ _LT_EOF _LT_TAGVAR(link_all_deplibs, $1)=yes ;; - netbsd*) + netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else @@ -4859,17 +5414,17 @@ _LT_EOF _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' @@ -4879,13 +5434,13 @@ _LT_EOF osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' @@ -4898,9 +5453,9 @@ _LT_EOF _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) @@ -5076,36 +5631,38 @@ x|xyes) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. - AC_MSG_CHECKING([whether -lc should be explicitly linked in]) - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if AC_TRY_EVAL(ac_compile) 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) - pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) - _LT_TAGVAR(allow_undefined_flag, $1)= - if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) - then - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - else - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - fi - _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)]) + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi @@ -5142,9 +5699,6 @@ _LT_TAGDECL([], [no_undefined_flag], [1], _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) -_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], - [[If ld is used when linking, flag to hardcode $libdir into a binary - during linking. This must work even if $libdir does not exist]]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], @@ -5170,8 +5724,6 @@ _LT_TAGDECL([], [inherit_rpath], [0], to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) -_LT_TAGDECL([], [fix_srcfile_path], [1], - [Fix the shell variable $srcfile for the compiler]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], @@ -5182,6 +5734,8 @@ _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented @@ -5275,37 +5829,22 @@ CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG -# _LT_PROG_CXX -# ------------ -# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++ -# compiler, we have our own version here. -m4_defun([_LT_PROG_CXX], -[ -pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes]) -AC_PROG_CXX -if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - AC_PROG_CXXCPP -else - _lt_caught_CXX_error=yes -fi -popdef([AC_MSG_ERROR]) -])# _LT_PROG_CXX - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([_LT_PROG_CXX], []) - - # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], -[AC_REQUIRE([_LT_PROG_CXX])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no @@ -5317,7 +5856,6 @@ _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported @@ -5327,6 +5865,8 @@ _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no @@ -5358,6 +5898,7 @@ if test "$_lt_caught_CXX_error" != yes; then # Allow CC to be a program name with arguments. lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX @@ -5375,6 +5916,7 @@ if test "$_lt_caught_CXX_error" != yes; then fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) @@ -5396,8 +5938,8 @@ if test "$_lt_caught_CXX_error" != yes; then # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' @@ -5429,7 +5971,7 @@ if test "$_lt_caught_CXX_error" != yes; then # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no @@ -5527,6 +6069,7 @@ if test "$_lt_caught_CXX_error" != yes; then fi fi + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. @@ -5537,10 +6080,10 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. - _LT_SYS_MODULE_PATH_AIX + _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' @@ -5549,14 +6092,19 @@ if test "$_lt_caught_CXX_error" != yes; then else # Determine the default libpath from the value encoded in an # empty executable. - _LT_SYS_MODULE_PATH_AIX + _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. @@ -5585,29 +6133,76 @@ if test "$_lt_caught_CXX_error" != yes; then esac ;; - cygwin* | mingw* | pw32*) - # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; @@ -5630,7 +6225,7 @@ if test "$_lt_caught_CXX_error" != yes; then esac ;; - freebsd[[12]]*) + freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no @@ -5649,6 +6244,11 @@ if test "$_lt_caught_CXX_error" != yes; then gnu*) ;; + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: @@ -5673,11 +6273,11 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no @@ -5738,7 +6338,7 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then @@ -5748,10 +6348,10 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi @@ -5781,7 +6381,7 @@ if test "$_lt_caught_CXX_error" != yes; then case $cc_basename in CC*) # SGI C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is @@ -5792,9 +6392,9 @@ if test "$_lt_caught_CXX_error" != yes; then *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes @@ -5805,7 +6405,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(inherit_rpath, $1)=yes ;; - linux* | k*bsd*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler @@ -5823,7 +6423,7 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' @@ -5860,26 +6460,26 @@ if test "$_lt_caught_CXX_error" != yes; then pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in - *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*) + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; - *) # Version 6 will use weak symbols + *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; @@ -5887,7 +6487,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ @@ -5906,9 +6506,9 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; - xl*) + xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' @@ -5928,13 +6528,13 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. - output_verbose_link_cmd='echo' + output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is @@ -6003,7 +6603,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi - output_verbose_link_cmd=echo + output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -6038,15 +6638,15 @@ if test "$_lt_caught_CXX_error" != yes; then case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; @@ -6062,17 +6662,17 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac @@ -6082,7 +6682,7 @@ if test "$_lt_caught_CXX_error" != yes; then # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support @@ -6118,7 +6718,7 @@ if test "$_lt_caught_CXX_error" != yes; then solaris*) case $cc_basename in - CC*) + CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' @@ -6139,7 +6739,7 @@ if test "$_lt_caught_CXX_error" != yes; then esac _LT_TAGVAR(link_all_deplibs, $1)=yes - output_verbose_link_cmd='echo' + output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is @@ -6159,14 +6759,14 @@ if test "$_lt_caught_CXX_error" != yes; then if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. @@ -6177,7 +6777,7 @@ if test "$_lt_caught_CXX_error" != yes; then # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' @@ -6231,6 +6831,10 @@ if test "$_lt_caught_CXX_error" != yes; then CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' @@ -6286,6 +6890,7 @@ if test "$_lt_caught_CXX_error" != yes; then fi # test -n "$compiler" CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC @@ -6300,6 +6905,29 @@ AC_LANG_POP ])# _LT_LANG_CXX_CONFIG +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose @@ -6308,6 +6936,7 @@ AC_LANG_POP # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= @@ -6357,7 +6986,20 @@ public class foo { } }; _LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF ]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then @@ -6369,7 +7011,7 @@ if AC_TRY_EVAL(ac_compile); then pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do - case $p in + case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. @@ -6378,13 +7020,22 @@ if AC_TRY_EVAL(ac_compile); then test $p = "-R"; then prev=$p continue - else - prev= fi + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac if test "$pre_test_object_deps_done" = no; then - case $p in - -L* | -R*) + case ${prev} in + -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. @@ -6404,8 +7055,10 @@ if AC_TRY_EVAL(ac_compile); then _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi + prev= ;; + *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. @@ -6441,6 +7094,7 @@ else fi $RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], @@ -6477,7 +7131,7 @@ linux*) solaris*) case $cc_basename in - CC*) + CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as @@ -6521,32 +7175,16 @@ _LT_TAGDECL([], [compiler_lib_search_path], [1], ])# _LT_SYS_HIDDEN_LIBDEPS -# _LT_PROG_F77 -# ------------ -# Since AC_PROG_F77 is broken, in that it returns the empty string -# if there is no fortran compiler, we have our own version here. -m4_defun([_LT_PROG_F77], -[ -pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes]) -AC_PROG_F77 -if test -z "$F77" || test "X$F77" = "Xno"; then - _lt_disable_F77=yes -fi -popdef([AC_MSG_ERROR]) -])# _LT_PROG_F77 - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([_LT_PROG_F77], []) - - # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], -[AC_REQUIRE([_LT_PROG_F77])dnl -AC_LANG_PUSH(Fortran 77) +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= @@ -6556,7 +7194,6 @@ _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no @@ -6565,6 +7202,8 @@ _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no @@ -6604,7 +7243,9 @@ if test "$_lt_disable_F77" != yes; then # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} + CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) @@ -6658,38 +7299,24 @@ if test "$_lt_disable_F77" != yes; then GCC=$lt_save_GCC CC="$lt_save_CC" + CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG -# _LT_PROG_FC -# ----------- -# Since AC_PROG_FC is broken, in that it returns the empty string -# if there is no fortran compiler, we have our own version here. -m4_defun([_LT_PROG_FC], -[ -pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes]) -AC_PROG_FC -if test -z "$FC" || test "X$FC" = "Xno"; then - _lt_disable_FC=yes -fi -popdef([AC_MSG_ERROR]) -])# _LT_PROG_FC - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([_LT_PROG_FC], []) - - # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], -[AC_REQUIRE([_LT_PROG_FC])dnl -AC_LANG_PUSH(Fortran) +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= @@ -6699,7 +7326,6 @@ _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no @@ -6708,6 +7334,8 @@ _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no @@ -6747,7 +7375,9 @@ if test "$_lt_disable_FC" != yes; then # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} + CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu @@ -6803,7 +7433,8 @@ if test "$_lt_disable_FC" != yes; then fi # test -n "$compiler" GCC=$lt_save_GCC - CC="$lt_save_CC" + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP @@ -6840,10 +7471,12 @@ _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. -lt_save_CC="$CC" +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" @@ -6853,6 +7486,8 @@ _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -6872,10 +7507,82 @@ fi AC_LANG_RESTORE GCC=$lt_save_GCC -CC="$lt_save_CC" +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler @@ -6907,9 +7614,11 @@ _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" +lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} +CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) @@ -6922,7 +7631,8 @@ fi GCC=$lt_save_GCC AC_LANG_RESTORE -CC="$lt_save_CC" +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG @@ -6942,6 +7652,13 @@ dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], @@ -6970,6 +7687,27 @@ AC_SUBST([GREP]) ]) +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates @@ -7062,8 +7800,8 @@ m4_defun([_LT_CHECK_SHELL_FEATURES], # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,, \ + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes @@ -7102,208 +7840,162 @@ _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES -# _LT_PROG_XSI_SHELLFNS -# --------------------- -# Bourne and XSI compatible variants of some useful shell functions. -m4_defun([_LT_PROG_XSI_SHELLFNS], -[case $xsi_shell in - yes) - cat << \_LT_EOF >> "$cfgfile" - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac -} - -# func_basename file -func_basename () -{ - func_basename_result="${1##*/}" -} - -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () -{ - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac - func_basename_result="${1##*/}" -} - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -func_stripname () -{ - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary parameter first. - func_stripname_result=${3} - func_stripname_result=${func_stripname_result#"${1}"} - func_stripname_result=${func_stripname_result%"${2}"} -} - -# func_opt_split -func_opt_split () -{ - func_opt_split_opt=${1%%=*} - func_opt_split_arg=${1#*=} -} +# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) +# ------------------------------------------------------ +# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and +# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. +m4_defun([_LT_PROG_FUNCTION_REPLACE], +[dnl { +sed -e '/^$1 ()$/,/^} # $1 /c\ +$1 ()\ +{\ +m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) +} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: +]) -# func_lo2o object -func_lo2o () -{ - case ${1} in - *.lo) func_lo2o_result=${1%.lo}.${objext} ;; - *) func_lo2o_result=${1} ;; - esac -} -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=${1%.*}.lo -} +# _LT_PROG_REPLACE_SHELLFNS +# ------------------------- +# Replace existing portable implementations of several shell functions with +# equivalent extended shell implementations where those features are available.. +m4_defun([_LT_PROG_REPLACE_SHELLFNS], +[if test x"$xsi_shell" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}"]) -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=$(( $[*] )) -} + _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"}]) -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=${#1} -} + _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl + func_split_long_opt_name=${1%%=*} + func_split_long_opt_arg=${1#*=}]) -_LT_EOF - ;; - *) # Bourne compatible functions. - cat << \_LT_EOF >> "$cfgfile" + _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} + _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac]) -# func_basename file -func_basename () -{ - func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` -} + _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) -dnl func_dirname_and_basename -dnl A portable version of this function is already defined in general.m4sh -dnl so there is no need for it here. + _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; - esac -} - -# sed scripts: -my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q' -my_sed_long_arg='1s/^-[[^=]]*=//' - -# func_opt_split -func_opt_split () -{ - func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` - func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` -} + _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) +fi -# func_lo2o object -func_lo2o () -{ - func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` -} +if test x"$lt_shell_append" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'` -} + _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl + func_quote_for_eval "${2}" +dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ + eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=`expr "$[@]"` -} - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len` -} - -_LT_EOF -esac + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi -case $lt_shell_append in - yes) - cat << \_LT_EOF >> "$cfgfile" +if test x"$_lt_function_replace_fail" = x":"; then + AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) +fi +]) -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "$[1]+=\$[2]" -} -_LT_EOF +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine which file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac ;; - *) - cat << \_LT_EOF >> "$cfgfile" - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "$[1]=\$$[1]\$[2]" -} - -_LT_EOF + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac ;; - esac + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac ]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 index e970119..5d9acd8 100644 --- a/m4/ltoptions.m4 +++ b/m4/ltoptions.m4 @@ -1,13 +1,14 @@ # Helper functions for option handling. -*- Autoconf -*- # -# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, +# Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. -# serial 6 ltoptions.m4 +# serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) @@ -125,7 +126,7 @@ LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in -*-*-cygwin* | *-*-mingw* | *-*-pw32*) +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) @@ -133,13 +134,13 @@ case $host in esac test -z "$AS" && AS=as -_LT_DECL([], [AS], [0], [Assembler program])dnl +_LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool -_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump -_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], @@ -325,9 +326,24 @@ dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], - [AS_HELP_STRING([--with-pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], - [pic_mode="$withval"], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for lt_pkg in $withval; do + IFS="$lt_save_ifs" + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 index 0d258e0..9000a05 100644 --- a/m4/ltsugar.m4 +++ b/m4/ltsugar.m4 @@ -1,13 +1,13 @@ # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # -# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. -# Written by Gary V. Vaughan, 2004 +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. -# serial 5 ltsugar.m4 +# serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) @@ -63,14 +63,14 @@ m4_define([lt_append], # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], -[m4_if([$2], [], [], - [m4_if([$4], [], [], - [lt_join(m4_quote(m4_default([$1], [[, ]])), - lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_prefix, [$2], - [m4_foreach(_Lt_suffix, lt_car([m4_shiftn(3, $@)]), - [_Lt_prefix[]$3[]_Lt_suffix ])])))))])])dnl -]) +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 index 45cb155..07a8602 100644 --- a/m4/ltversion.m4 +++ b/m4/ltversion.m4 @@ -7,17 +7,17 @@ # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. -# Generated from ltversion.in. +# @configure_input@ -# serial 2976 ltversion.m4 +# serial 3337 ltversion.m4 # This file is part of GNU Libtool -m4_define([LT_PACKAGE_VERSION], [2.2.4]) -m4_define([LT_PACKAGE_REVISION], [1.2976]) +m4_define([LT_PACKAGE_VERSION], [2.4.2]) +m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.2.4' -macro_revision='1.2976' +[macro_version='2.4.2' +macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 index 637bb20..c573da9 100644 --- a/m4/lt~obsolete.m4 +++ b/m4/lt~obsolete.m4 @@ -1,13 +1,13 @@ # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # -# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. -# serial 4 lt~obsolete.m4 +# serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # @@ -77,7 +77,6 @@ m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) -m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) @@ -90,3 +89,10 @@ m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/m4/stl_hash.m4 b/m4/stl_hash.m4 index 08813c9..0722b14 100644 --- a/m4/stl_hash.m4 +++ b/m4/stl_hash.m4 @@ -1,60 +1,72 @@ -# We check two things: where the include file is for hash_map, and -# what namespace hash_map lives in within that include file. We +# We check two things: where the include file is for +# unordered_map/hash_map (we prefer the first form), and what +# namespace unordered/hash_map lives in within that include file. We # include AC_TRY_COMPILE for all the combinations we've seen in the -# wild. We define one of HAVE_HASH_MAP or HAVE_EXT_HASH_MAP depending -# on location, and HASH_NAMESPACE to be the namespace hash_map is -# defined in. -# -# Ideally we'd use AC_CACHE_CHECK, but that only lets us store one value -# at a time, and we need to store two (filename and namespace). -# prints messages itself, so we have to do the message-printing ourselves -# via AC_MSG_CHECKING + AC_MSG_RESULT. (TODO(csilvers): can we cache?) +# wild. We define HASH_MAP_H to the location of the header file, and +# HASH_NAMESPACE to the namespace the class (unordered_map or +# hash_map) is in. We define HAVE_UNORDERED_MAP if the class we found +# is named unordered_map, or leave it undefined if not. +# This also checks if unordered map exists. AC_DEFUN([AC_CXX_STL_HASH], - [AC_MSG_CHECKING(the location of hash_map) - AC_LANG_SAVE + [ + AC_MSG_CHECKING(the location of hash_map) + AC_LANG_SAVE AC_LANG_CPLUSPLUS - ac_cv_cxx_hash_map_header="" - ac_cv_cxx_hash_map_class="" - for location in [tr1/unordered_map ext/hash_map hash_map]; do - for namespace in [std::tr1 __gnu_cxx "" std stdext]; do - for name in [unordered_map hash_map]; do - - if test -z "$ac_cv_cxx_hash_map_header"; then - - # On OSX 1.5 / GCC 4.0.1 (the standard compiler on that platform), - # calling find() on a const unordered_map does not compile. So, we - # include a call to find() in our test to detect this broken - # implementation and avoid using it. Note that ext/hash_map works - # fine on this platform, so we'll end up using that. - AC_TRY_COMPILE([#include <$location>], - [const ${namespace}::$name t; - t.find(1);], - [ac_cv_cxx_hash_map_header="<$location>"; - ac_cv_cxx_hash_namespace="$namespace"; - ac_cv_cxx_hash_map_class="$name";]) - fi - done + ac_cv_cxx_hash_map="" + # First try unordered_map, but not on gcc's before 4.2 -- I've + # seen unexplainable unordered_map bugs with -O2 on older gcc's. + AC_TRY_COMPILE([#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)) + # error GCC too old for unordered_map + #endif + ], + [/* no program body necessary */], + [stl_hash_old_gcc=no], + [stl_hash_old_gcc=yes]) + for location in unordered_map tr1/unordered_map; do + for namespace in std std::tr1; do + if test -z "$ac_cv_cxx_hash_map" -a "$stl_hash_old_gcc" != yes; then + # Some older gcc's have a buggy tr1, so test a bit of code. + AC_TRY_COMPILE([#include <$location>], + [const ${namespace}::unordered_map t; + return t.find(5) == t.end();], + [ac_cv_cxx_hash_map="<$location>"; + ac_cv_cxx_hash_namespace="$namespace"; + ac_cv_cxx_hash_map_class="unordered_map";]) + fi done done - ac_cv_cxx_hash_set_header=`echo "$ac_cv_cxx_hash_map_header" | sed s/map/set/`; + # Now try hash_map + for location in ext/hash_map hash_map; do + for namespace in __gnu_cxx "" std stdext; do + if test -z "$ac_cv_cxx_hash_map"; then + AC_TRY_COMPILE([#include <$location>], + [${namespace}::hash_map t], + [ac_cv_cxx_hash_map="<$location>"; + ac_cv_cxx_hash_namespace="$namespace"; + ac_cv_cxx_hash_map_class="hash_map";]) + fi + done + done + ac_cv_cxx_hash_set=`echo "$ac_cv_cxx_hash_map" | sed s/map/set/`; ac_cv_cxx_hash_set_class=`echo "$ac_cv_cxx_hash_map_class" | sed s/map/set/`; - if test -n "$ac_cv_cxx_hash_map_header"; then + if test -n "$ac_cv_cxx_hash_map"; then AC_DEFINE(HAVE_HASH_MAP, 1, [define if the compiler has hash_map]) AC_DEFINE(HAVE_HASH_SET, 1, [define if the compiler has hash_set]) - AC_DEFINE_UNQUOTED(HASH_MAP_H,$ac_cv_cxx_hash_map_header, - [the location of ]) - AC_DEFINE_UNQUOTED(HASH_SET_H,$ac_cv_cxx_hash_set_header, - [the location of ]) + AC_DEFINE_UNQUOTED(HASH_MAP_H,$ac_cv_cxx_hash_map, + [the location of or ]) + AC_DEFINE_UNQUOTED(HASH_SET_H,$ac_cv_cxx_hash_set, + [the location of or ]) + AC_DEFINE_UNQUOTED(HASH_NAMESPACE,$ac_cv_cxx_hash_namespace, + [the namespace of hash_map/hash_set]) AC_DEFINE_UNQUOTED(HASH_MAP_CLASS,$ac_cv_cxx_hash_map_class, - [the name of ]) + [the name of ]) AC_DEFINE_UNQUOTED(HASH_SET_CLASS,$ac_cv_cxx_hash_set_class, [the name of ]) - AC_DEFINE_UNQUOTED(HASH_NAMESPACE,$ac_cv_cxx_hash_namespace, - [the namespace of hash_map/hash_set]) - AC_MSG_RESULT([$ac_cv_cxx_hash_map_header]) + AC_MSG_RESULT([$ac_cv_cxx_hash_map]) else AC_MSG_RESULT() AC_MSG_WARN([could not find an STL hash_map]) fi ]) + diff --git a/missing b/missing index 1c8ff70..86a8fc3 100755 --- a/missing +++ b/missing @@ -1,10 +1,10 @@ #! /bin/sh # Common stub for a few missing GNU programs while installing. -scriptversion=2006-05-10.23 +scriptversion=2012-01-06.13; # UTC -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 -# Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, +# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify @@ -18,9 +18,7 @@ scriptversion=2006-05-10.23 # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -86,9 +84,11 @@ Supported PROGRAM values: help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] +Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and +\`g' are ignored when checking the name. + Send bug reports to ." exit $? ;; @@ -106,23 +106,21 @@ Send bug reports to ." esac +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect -# the program). +# the program). This is about non-GNU programs, so use $1 not +# $program. case $1 in - lex|yacc) + lex*|yacc*) # Not GNU programs, they don't have --version. ;; - tar) - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - exit 1 - fi - ;; - *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. @@ -138,7 +136,7 @@ esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. -case $1 in +case $program in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if @@ -148,7 +146,7 @@ WARNING: \`$1' is $msg. You should only need it if touch aclocal.m4 ;; - autoconf) + autoconf*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the @@ -157,7 +155,7 @@ WARNING: \`$1' is $msg. You should only need it if touch configure ;; - autoheader) + autoheader*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want @@ -187,7 +185,7 @@ WARNING: \`$1' is $msg. You should only need it if while read f; do touch "$f"; done ;; - autom4te) + autom4te*) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the @@ -210,7 +208,7 @@ WARNING: \`$1' is needed, but is $msg. fi ;; - bison|yacc) + bison*|yacc*) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package @@ -218,7 +216,7 @@ WARNING: \`$1' $msg. You should only need it if \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then - eval LASTARG="\${$#}" + eval LASTARG=\${$#} case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` @@ -240,7 +238,7 @@ WARNING: \`$1' $msg. You should only need it if fi ;; - lex|flex) + lex*|flex*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package @@ -248,7 +246,7 @@ WARNING: \`$1' is $msg. You should only need it if \`Flex' from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then - eval LASTARG="\${$#}" + eval LASTARG=\${$#} case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` @@ -263,7 +261,7 @@ WARNING: \`$1' is $msg. You should only need it if fi ;; - help2man) + help2man*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the @@ -277,11 +275,11 @@ WARNING: \`$1' is $msg. You should only need it if else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" - exit 1 + exit $? fi ;; - makeinfo) + makeinfo*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file @@ -310,41 +308,6 @@ WARNING: \`$1' is $msg. You should only need it if touch $file ;; - tar) - shift - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case $firstarg in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case $firstarg in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. @@ -363,5 +326,6 @@ exit 0 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" # End: diff --git a/more_tests/Makefile b/more_tests/Makefile new file mode 100755 index 0000000..286cf0f --- /dev/null +++ b/more_tests/Makefile @@ -0,0 +1,41 @@ +# Additional tests to run before releasing a package. +# +# Run like: +# make PACKAGE=/path/to/protobuf-VERSION.tar.gz +# +# Some of these tests require tools or make assumptions that may not be +# available on end-user machines, so these cannot be part of "make check". For +# example, we test that the headers compile with strict warning settings, but +# since different compilers produce wildly different warnings we cannot assume +# that this test will pass everywhere. If we ran it as part of "make check", +# it could unnecessarily block users from running the real tests just because +# their compiler produces some extra warnings that probably aren't a big deal. +# So we run it separately. + +all: header_warning_test + +clean: + rm -rf src target header_warning_test.cc header_warning_test.o header_warning_test + +# Unpack the package into src, then install it into target. +PACKAGE=protobuf.tar.gz + +src: $(PACKAGE) + tar zxvf $(PACKAGE) + mv `basename $(PACKAGE) .tar.gz` src + +target: src + (cd src && ./configure --prefix=$$PWD/../target --disable-shared) + (cd src && make -j4 check) + (cd src && make install) + +# Verify that headers produce no warnings even under strict settings. +header_warning_test.cc: target + ( (cd target/include && find google/protobuf -name '*.h') | \ + awk '{print "#include \""$$1"\""} ' > header_warning_test.cc ) + +header_warning_test: header_warning_test.cc + # TODO(kenton): Consider adding -pedantic and -Weffc++. Currently these + # produce tons of extra warnings so we'll need to do some work first. + g++ -Itarget/include -Wall -Werror -Wsign-compare -O2 -c header_warning_test.cc + touch header_warning_test diff --git a/post_process_dist.sh b/post_process_dist.sh new file mode 100755 index 0000000..7b2e599 --- /dev/null +++ b/post_process_dist.sh @@ -0,0 +1,60 @@ +#! /bin/sh + +# This script takes the result of "make dist" and: +# 1) Unpacks it. +# 2) Ensures all contents are user-writable. Some version control systems +# keep code read-only until you explicitly ask to edit it, and the normal +# "make dist" process does not correct for this, so the result is that +# the entire dist is still marked read-only when unpacked, which is +# annoying. So, we fix it. +# 3) Convert MSVC project files to MSVC 2005, so that anyone who has version +# 2005 *or* 2008 can open them. (In version control, we keep things in +# MSVC 2008 format since that's what we use in development.) +# 4) Uses the result to create .tar.gz, .tar.bz2, and .zip versions and +# deposites them in the "dist" directory. In the .zip version, all +# non-testdata .txt files are converted to Windows-style line endings. +# 5) Cleans up after itself. + +if [ "$1" == "" ]; then + echo "USAGE: $1 DISTFILE" >&2 + exit 1 +fi + +if [ ! -e $1 ]; then + echo $1": File not found." >&2 + exit 1 +fi + +set -ex + +BASENAME=`basename $1 .tar.gz` + +# Create a directory called "dist", copy the tarball there and unpack it. +mkdir dist +cp $1 dist +cd dist +tar zxvf $BASENAME.tar.gz +rm $BASENAME.tar.gz + +# Set the entire contents to be user-writable. +chmod -R u+w $BASENAME + +# Convert the MSVC projects to MSVC 2005 format. +cd $BASENAME/vsprojects +./convert2008to2005.sh +cd .. + +# Build the dist again in .tar.gz and .tar.bz2 formats. +./configure +make dist-gzip +make dist-bzip2 + +# Convert all text files to use DOS-style line endings, then build a .zip +# distribution. +todos *.txt */*.txt +make dist-zip + +# Clean up. +mv $BASENAME.tar.gz $BASENAME.tar.bz2 $BASENAME.zip .. +cd .. +rm -rf $BASENAME diff --git a/prebuilts/Android.mk b/prebuilts/Android.mk deleted file mode 100644 index 82a4157..0000000 --- a/prebuilts/Android.mk +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright (C) 2014 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# - -# Prebuilts of the old 2.3.0 libprotobuf library. -# DEPRECATED: It is rare that you should need to depend on these libraries -# directly. Instead prefer setting LOCAL_PROTOC_OPTIMIZE_TYPE which will -# automatically pull in any dependent libraries, or using the versionless -# definitions of these libraries. - -# Device Java prebuilts - -include $(CLEAR_VARS) - -LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \ - libprotobuf-java-2.3.0-lite:prebuilts/libprotobuf-java-2.3.0-lite.jar \ - libprotobuf-java-2.3.0-micro:prebuilts/libprotobuf-java-2.3.0-micro.jar \ - libprotobuf-java-2.3.0-nano:prebuilts/libprotobuf-java-2.3.0-nano.jar - -include $(BUILD_MULTI_PREBUILT) - -# Host Java prebuilts - -include $(CLEAR_VARS) - -LOCAL_IS_HOST_MODULE := true - -LOCAL_PREBUILT_JAVA_LIBRARIES := \ - host-libprotobuf-java-2.3.0-lite:prebuilts/host-libprotobuf-java-2.3.0-lite.jar \ - host-libprotobuf-java-2.3.0-micro:prebuilts/host-libprotobuf-java-2.3.0-micro.jar \ - host-libprotobuf-java-2.3.0-nano:prebuilts/host-libprotobuf-java-2.3.0-nano.jar - -include $(BUILD_MULTI_PREBUILT) - -# Device C++ static library prebuilts - -include $(CLEAR_VARS) - -LOCAL_MODULE := libprotobuf-cpp-2.3.0-full -LOCAL_MODULE_CLASS := STATIC_LIBRARIES -LOCAL_MODULE_SUFFIX := .a -LOCAL_SRC_FILES_arm := prebuilts/arm/libprotobuf-cpp-2.3.0-full.a -LOCAL_SRC_FILES_arm64 := prebuilts/arm64/libprotobuf-cpp-2.3.0-full.a -LOCAL_SRC_FILES_mips := prebuilts/mips/libprotobuf-cpp-2.3.0-full.a -LOCAL_SRC_FILES_mips64 := prebuilts/mips64/libprotobuf-cpp-2.3.0-full.a -LOCAL_SRC_FILES_x86 := prebuilts/x86/libprotobuf-cpp-2.3.0-full.a -LOCAL_SRC_FILES_x86_64 := prebuilts/x86_64/libprotobuf-cpp-2.3.0-full.a -LOCAL_MODULE_TARGET_ARCH := arm arm64 mips mips64 x86 x86_64 -LOCAL_MULTILIB := both - -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) - -LOCAL_MODULE := libprotobuf-cpp-2.3.0-full-gnustl-rtti -LOCAL_MODULE_CLASS := STATIC_LIBRARIES -LOCAL_MODULE_SUFFIX := .a -LOCAL_SRC_FILES_arm := prebuilts/arm/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a -LOCAL_SRC_FILES_arm64 := prebuilts/arm64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a -LOCAL_SRC_FILES_mips := prebuilts/mips/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a -LOCAL_SRC_FILES_mips64 := prebuilts/mips64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a -LOCAL_SRC_FILES_x86 := prebuilts/x86/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a -LOCAL_SRC_FILES_x86_64 := prebuilts/x86_64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a -LOCAL_MODULE_TARGET_ARCH := arm arm64 mips mips64 x86 x86_64 -LOCAL_MULTILIB := both - -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) - -LOCAL_MODULE := libprotobuf-cpp-2.3.0-lite -LOCAL_MODULE_CLASS := STATIC_LIBRARIES -LOCAL_MODULE_SUFFIX := .a -LOCAL_SRC_FILES_arm := prebuilts/arm/libprotobuf-cpp-2.3.0-lite.a -LOCAL_SRC_FILES_arm64 := prebuilts/arm64/libprotobuf-cpp-2.3.0-lite.a -LOCAL_SRC_FILES_mips := prebuilts/mips/libprotobuf-cpp-2.3.0-lite.a -LOCAL_SRC_FILES_mips64 := prebuilts/mips64/libprotobuf-cpp-2.3.0-lite.a -LOCAL_SRC_FILES_x86 := prebuilts/x86/libprotobuf-cpp-2.3.0-lite.a -LOCAL_SRC_FILES_x86_64 := prebuilts/x86_64/libprotobuf-cpp-2.3.0-lite.a -LOCAL_MODULE_TARGET_ARCH := arm arm64 mips mips64 x86 x86_64 -LOCAL_MULTILIB := both - -include $(BUILD_PREBUILT) - diff --git a/prebuilts/arm/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a b/prebuilts/arm/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a deleted file mode 100644 index 5d8356b..0000000 Binary files a/prebuilts/arm/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a and /dev/null differ diff --git a/prebuilts/arm/libprotobuf-cpp-2.3.0-full.a b/prebuilts/arm/libprotobuf-cpp-2.3.0-full.a deleted file mode 100644 index 13caee8..0000000 Binary files a/prebuilts/arm/libprotobuf-cpp-2.3.0-full.a and /dev/null differ diff --git a/prebuilts/arm/libprotobuf-cpp-2.3.0-lite.a b/prebuilts/arm/libprotobuf-cpp-2.3.0-lite.a deleted file mode 100644 index 298b308..0000000 Binary files a/prebuilts/arm/libprotobuf-cpp-2.3.0-lite.a and /dev/null differ diff --git a/prebuilts/arm64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a b/prebuilts/arm64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a deleted file mode 100644 index cea2882..0000000 Binary files a/prebuilts/arm64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a and /dev/null differ diff --git a/prebuilts/arm64/libprotobuf-cpp-2.3.0-full.a b/prebuilts/arm64/libprotobuf-cpp-2.3.0-full.a deleted file mode 100644 index 5a22df1..0000000 Binary files a/prebuilts/arm64/libprotobuf-cpp-2.3.0-full.a and /dev/null differ diff --git a/prebuilts/arm64/libprotobuf-cpp-2.3.0-lite.a b/prebuilts/arm64/libprotobuf-cpp-2.3.0-lite.a deleted file mode 100644 index ab198ea..0000000 Binary files a/prebuilts/arm64/libprotobuf-cpp-2.3.0-lite.a and /dev/null differ diff --git a/prebuilts/host-libprotobuf-java-2.3.0-lite.jar b/prebuilts/host-libprotobuf-java-2.3.0-lite.jar deleted file mode 100644 index 77a9617..0000000 Binary files a/prebuilts/host-libprotobuf-java-2.3.0-lite.jar and /dev/null differ diff --git a/prebuilts/host-libprotobuf-java-2.3.0-micro.jar b/prebuilts/host-libprotobuf-java-2.3.0-micro.jar deleted file mode 100644 index 9cedc4a..0000000 Binary files a/prebuilts/host-libprotobuf-java-2.3.0-micro.jar and /dev/null differ diff --git a/prebuilts/host-libprotobuf-java-2.3.0-nano.jar b/prebuilts/host-libprotobuf-java-2.3.0-nano.jar deleted file mode 100644 index 660b94a..0000000 Binary files a/prebuilts/host-libprotobuf-java-2.3.0-nano.jar and /dev/null differ diff --git a/prebuilts/libprotobuf-java-2.3.0-lite.jar b/prebuilts/libprotobuf-java-2.3.0-lite.jar deleted file mode 100644 index 12f8512..0000000 Binary files a/prebuilts/libprotobuf-java-2.3.0-lite.jar and /dev/null differ diff --git a/prebuilts/libprotobuf-java-2.3.0-micro.jar b/prebuilts/libprotobuf-java-2.3.0-micro.jar deleted file mode 100644 index 95aa84e..0000000 Binary files a/prebuilts/libprotobuf-java-2.3.0-micro.jar and /dev/null differ diff --git a/prebuilts/libprotobuf-java-2.3.0-nano.jar b/prebuilts/libprotobuf-java-2.3.0-nano.jar deleted file mode 100644 index 054cd1e..0000000 Binary files a/prebuilts/libprotobuf-java-2.3.0-nano.jar and /dev/null differ diff --git a/prebuilts/mips/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a b/prebuilts/mips/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a deleted file mode 100644 index 8fa3d05..0000000 Binary files a/prebuilts/mips/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a and /dev/null differ diff --git a/prebuilts/mips/libprotobuf-cpp-2.3.0-full.a b/prebuilts/mips/libprotobuf-cpp-2.3.0-full.a deleted file mode 100644 index 063daae..0000000 Binary files a/prebuilts/mips/libprotobuf-cpp-2.3.0-full.a and /dev/null differ diff --git a/prebuilts/mips/libprotobuf-cpp-2.3.0-lite.a b/prebuilts/mips/libprotobuf-cpp-2.3.0-lite.a deleted file mode 100644 index 8e4be02..0000000 Binary files a/prebuilts/mips/libprotobuf-cpp-2.3.0-lite.a and /dev/null differ diff --git a/prebuilts/mips64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a b/prebuilts/mips64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a deleted file mode 100644 index e3092b8..0000000 Binary files a/prebuilts/mips64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a and /dev/null differ diff --git a/prebuilts/mips64/libprotobuf-cpp-2.3.0-full.a b/prebuilts/mips64/libprotobuf-cpp-2.3.0-full.a deleted file mode 100644 index 5e48b8b..0000000 Binary files a/prebuilts/mips64/libprotobuf-cpp-2.3.0-full.a and /dev/null differ diff --git a/prebuilts/mips64/libprotobuf-cpp-2.3.0-lite.a b/prebuilts/mips64/libprotobuf-cpp-2.3.0-lite.a deleted file mode 100644 index 86d6a21..0000000 Binary files a/prebuilts/mips64/libprotobuf-cpp-2.3.0-lite.a and /dev/null differ diff --git a/prebuilts/x86/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a b/prebuilts/x86/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a deleted file mode 100644 index 6ddf739..0000000 Binary files a/prebuilts/x86/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a and /dev/null differ diff --git a/prebuilts/x86/libprotobuf-cpp-2.3.0-full.a b/prebuilts/x86/libprotobuf-cpp-2.3.0-full.a deleted file mode 100644 index e4bab62..0000000 Binary files a/prebuilts/x86/libprotobuf-cpp-2.3.0-full.a and /dev/null differ diff --git a/prebuilts/x86/libprotobuf-cpp-2.3.0-lite.a b/prebuilts/x86/libprotobuf-cpp-2.3.0-lite.a deleted file mode 100644 index 36c1aa2..0000000 Binary files a/prebuilts/x86/libprotobuf-cpp-2.3.0-lite.a and /dev/null differ diff --git a/prebuilts/x86_64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a b/prebuilts/x86_64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a deleted file mode 100644 index 5e48557..0000000 Binary files a/prebuilts/x86_64/libprotobuf-cpp-2.3.0-full-gnustl-rtti.a and /dev/null differ diff --git a/prebuilts/x86_64/libprotobuf-cpp-2.3.0-full.a b/prebuilts/x86_64/libprotobuf-cpp-2.3.0-full.a deleted file mode 100644 index b0dab22..0000000 Binary files a/prebuilts/x86_64/libprotobuf-cpp-2.3.0-full.a and /dev/null differ diff --git a/prebuilts/x86_64/libprotobuf-cpp-2.3.0-lite.a b/prebuilts/x86_64/libprotobuf-cpp-2.3.0-lite.a deleted file mode 100644 index 48ffb56..0000000 Binary files a/prebuilts/x86_64/libprotobuf-cpp-2.3.0-lite.a and /dev/null differ diff --git a/protobuf.pc.in b/protobuf.pc.in index 8a53a43..29f2487 100644 --- a/protobuf.pc.in +++ b/protobuf.pc.in @@ -6,7 +6,8 @@ includedir=@includedir@ Name: Protocol Buffers Description: Google's Data Interchange Format Version: @VERSION@ -Libs: -L${libdir} -lprotobuf @LIBS@ @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ +Libs: -L${libdir} -lprotobuf @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ +Libs.private: @LIBS@ Cflags: -I${includedir} @PTHREAD_CFLAGS@ # Commented out because it crashes pkg-config *sigh*: # http://bugs.freedesktop.org/show_bug.cgi?id=13265 diff --git a/python/README.txt b/python/README.txt index 96f1a73..adfa46b 100644 --- a/python/README.txt +++ b/python/README.txt @@ -43,9 +43,13 @@ Installation $ protoc --version -4) Run the tests: +4) Build and run the tests: - $ python setup.py test + $ python setup.py build + $ python setup.py google_test + + If you want to test c++ implementation, run: + $ python setup.py test --cpp_implementation If some tests fail, this library may not work correctly on your system. Continue at your own risk. @@ -61,8 +65,13 @@ Installation 5) Install: $ python setup.py install + or: + $ python setup.py install --cpp_implementation This step may require superuser privileges. + NOTE: To use C++ implementation, you need to install C++ protobuf runtime + library of the same version and export the environment variable before this + step. See the "C++ Implementation" section below for more details. Usage ===== @@ -71,3 +80,26 @@ The complete documentation for Protocol Buffers is available via the web at: http://code.google.com/apis/protocolbuffers/ + +C++ Implementation +================== + +The C++ implementation for Python messages is built as a Python extension to +improve the overall protobuf Python performance. + +To use the C++ implementation, you need to: +1) Install the C++ protobuf runtime library, please see instructions in the + parent directory. +2) Export an environment variable: + + $ export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp + $ export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2 + +You need to export this variable before running setup.py script to build and +install the extension. You must also set the variable at runtime, otherwise +the pure-Python implementation will be used. In a future release, we will +change the default so that C++ implementation is used whenever it is available. +It is strongly recommended to run `python setup.py test` after setting the +variable to "cpp", so the tests will be against C++ implemented Python +messages. + diff --git a/python/ez_setup.py b/python/ez_setup.py index b7a9849..3aec98e 100755 --- a/python/ez_setup.py +++ b/python/ez_setup.py @@ -2,7 +2,7 @@ # This file was obtained from: # http://peak.telecommunity.com/dist/ez_setup.py -# on 2009/4/17. +# on 2011/1/21. """Bootstrap setuptools installation @@ -19,7 +19,7 @@ the appropriate options to ``use_setuptools()``. This file can also be run as a script to install or upgrade setuptools. """ import sys -DEFAULT_VERSION = "0.6c9" +DEFAULT_VERSION = "0.6c11" DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3] md5_data = { @@ -33,6 +33,14 @@ md5_data = { 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', + 'setuptools-0.6c10-py2.3.egg': 'ce1e2ab5d3a0256456d9fc13800a7090', + 'setuptools-0.6c10-py2.4.egg': '57d6d9d6e9b80772c59a53a8433a5dd4', + 'setuptools-0.6c10-py2.5.egg': 'de46ac8b1c97c895572e5e8596aeb8c7', + 'setuptools-0.6c10-py2.6.egg': '58ea40aef06da02ce641495523a0b7f5', + 'setuptools-0.6c11-py2.3.egg': '2baeac6e13d414a9d28e7ba5b5a596de', + 'setuptools-0.6c11-py2.4.egg': 'bd639f9b0eac4c42497034dec2ec0c2b', + 'setuptools-0.6c11-py2.5.egg': '64c94f3bf7a72a13ec83e0b24f2749b2', + 'setuptools-0.6c11-py2.6.egg': 'bfa92100bd772d5a213eedd356d64086', 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', @@ -99,6 +107,7 @@ def use_setuptools( except ImportError: return do_download() try: + return do_download() pkg_resources.require("setuptools>="+version); return except pkg_resources.VersionConflict, e: if was_imported: @@ -109,11 +118,11 @@ def use_setuptools( "\n\n(Currently using %r)" ) % (version, e.args[0]) sys.exit(2) - else: - del pkg_resources, sys.modules['pkg_resources'] # reload ok - return do_download() except pkg_resources.DistributionNotFound: - return do_download() + pass + + del pkg_resources, sys.modules['pkg_resources'] # reload ok + return do_download() def download_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, @@ -273,9 +282,3 @@ if __name__=='__main__': update_md5(sys.argv[2:]) else: main(sys.argv[1:]) - - - - - - diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py index aa4ab96..555498d 100755 --- a/python/google/protobuf/descriptor.py +++ b/python/google/protobuf/descriptor.py @@ -28,15 +28,9 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# TODO(robinson): We probably need to provide deep-copy methods for -# descriptor types. When a FieldDescriptor is passed into -# Descriptor.__init__(), we should make a deep copy and then set -# containing_type on it. Alternatively, we could just get -# rid of containing_type (iit's not needed for reflection.py, at least). +# Needs to stay compatible with Python 2.5 due to GAE. # -# TODO(robinson): Print method? -# -# TODO(robinson): Useful __repr__? +# Copyright 2007 Google Inc. All Rights Reserved. """Descriptors essentially contain exactly the information found in a .proto file, in types that make this information accessible in Python. @@ -44,11 +38,28 @@ file, in types that make this information accessible in Python. __author__ = 'robinson@google.com (Will Robinson)' +from google.protobuf.internal import api_implementation + + +if api_implementation.Type() == 'cpp': + # Used by MakeDescriptor in cpp mode + import os + import uuid + + if api_implementation.Version() == 2: + from google.protobuf.pyext import _message + else: + from google.protobuf.internal import cpp_message + class Error(Exception): """Base error for this module.""" +class TypeTransformationError(Error): + """Error transforming between python proto type and corresponding C++ type.""" + + class DescriptorBase(object): """Descriptors base class. @@ -75,6 +86,18 @@ class DescriptorBase(object): # Does this descriptor have non-default options? self.has_options = options is not None + def _SetOptions(self, options, options_class_name): + """Sets the descriptor's options + + This function is used in generated proto2 files to update descriptor + options. It must not be used outside proto2. + """ + self._options = options + self._options_class_name = options_class_name + + # Does this descriptor have non-default options? + self.has_options = options is not None + def GetOptions(self): """Retrieves descriptor options. @@ -204,13 +227,21 @@ class Descriptor(_NestedDescriptorBase): options: (descriptor_pb2.MessageOptions) Protocol message options or None to use default message options. + oneofs: (list of OneofDescriptor) The list of descriptors for oneof fields + in this message. + oneofs_by_name: (dict str -> OneofDescriptor) Same objects as in |oneofs|, + but indexed by "name" attribute. + file: (FileDescriptor) Reference to file descriptor. """ + # NOTE(tmarek): The file argument redefining a builtin is nothing we can + # fix right now since we don't know how many clients already rely on the + # name of the argument. def __init__(self, name, full_name, filename, containing_type, fields, nested_types, enum_types, extensions, options=None, - is_extendable=True, extension_ranges=None, file=None, - serialized_start=None, serialized_end=None): + is_extendable=True, extension_ranges=None, oneofs=None, + file=None, serialized_start=None, serialized_end=None): # pylint:disable=redefined-builtin """Arguments to __init__() are as described in the description of Descriptor fields above. @@ -220,7 +251,7 @@ class Descriptor(_NestedDescriptorBase): super(Descriptor, self).__init__( options, 'MessageOptions', name, full_name, file, containing_type, serialized_start=serialized_start, - serialized_end=serialized_start) + serialized_end=serialized_end) # We have fields in addition to fields_by_name and fields_by_number, # so that: @@ -234,6 +265,8 @@ class Descriptor(_NestedDescriptorBase): self.fields_by_name = dict((f.name, f) for f in fields) self.nested_types = nested_types + for nested_type in nested_types: + nested_type.containing_type = self self.nested_types_by_name = dict((t.name, t) for t in nested_types) self.enum_types = enum_types @@ -249,9 +282,28 @@ class Descriptor(_NestedDescriptorBase): self.extensions_by_name = dict((f.name, f) for f in extensions) self.is_extendable = is_extendable self.extension_ranges = extension_ranges + self.oneofs = oneofs if oneofs is not None else [] + self.oneofs_by_name = dict((o.name, o) for o in self.oneofs) + for oneof in self.oneofs: + oneof.containing_type = self - self._serialized_start = serialized_start - self._serialized_end = serialized_end + def EnumValueName(self, enum, value): + """Returns the string name of an enum value. + + This is just a small helper method to simplify a common operation. + + Args: + enum: string name of the Enum. + value: int, value of the enum. + + Returns: + string name of the enum value. + + Raises: + KeyError if either the Enum doesn't exist or the value is not a valid + value for the enum. + """ + return self.enum_types_by_name[enum].values_by_number[value].name def CopyToProto(self, proto): """Copies this to a descriptor_pb2.DescriptorProto. @@ -278,7 +330,7 @@ class FieldDescriptor(DescriptorBase): """Descriptor for a single field in a .proto file. - A FieldDescriptor instance has the following attriubtes: + A FieldDescriptor instance has the following attributes: name: (str) Name of this field, exactly as it appears in .proto. full_name: (str) Name of this field, including containing scope. This is @@ -319,6 +371,9 @@ class FieldDescriptor(DescriptorBase): options: (descriptor_pb2.FieldOptions) Protocol message field options or None to use default field options. + + containing_oneof: (OneofDescriptor) If the field is a member of a oneof + union, contains its descriptor. Otherwise, None. """ # Must be consistent with C++ FieldDescriptor::Type enum in @@ -361,6 +416,27 @@ class FieldDescriptor(DescriptorBase): CPPTYPE_MESSAGE = 10 MAX_CPPTYPE = 10 + _PYTHON_TO_CPP_PROTO_TYPE_MAP = { + TYPE_DOUBLE: CPPTYPE_DOUBLE, + TYPE_FLOAT: CPPTYPE_FLOAT, + TYPE_ENUM: CPPTYPE_ENUM, + TYPE_INT64: CPPTYPE_INT64, + TYPE_SINT64: CPPTYPE_INT64, + TYPE_SFIXED64: CPPTYPE_INT64, + TYPE_UINT64: CPPTYPE_UINT64, + TYPE_FIXED64: CPPTYPE_UINT64, + TYPE_INT32: CPPTYPE_INT32, + TYPE_SFIXED32: CPPTYPE_INT32, + TYPE_SINT32: CPPTYPE_INT32, + TYPE_UINT32: CPPTYPE_UINT32, + TYPE_FIXED32: CPPTYPE_UINT32, + TYPE_BYTES: CPPTYPE_STRING, + TYPE_STRING: CPPTYPE_STRING, + TYPE_BOOL: CPPTYPE_BOOL, + TYPE_MESSAGE: CPPTYPE_MESSAGE, + TYPE_GROUP: CPPTYPE_MESSAGE + } + # Must be consistent with C++ FieldDescriptor::Label enum in # descriptor.h. # @@ -370,10 +446,16 @@ class FieldDescriptor(DescriptorBase): LABEL_REPEATED = 3 MAX_LABEL = 3 + # Must be consistent with C++ constants kMaxNumber, kFirstReservedNumber, + # and kLastReservedNumber in descriptor.h + MAX_FIELD_NUMBER = (1 << 29) - 1 + FIRST_RESERVED_FIELD_NUMBER = 19000 + LAST_RESERVED_FIELD_NUMBER = 19999 + def __init__(self, name, full_name, index, number, type, cpp_type, label, default_value, message_type, enum_type, containing_type, is_extension, extension_scope, options=None, - has_default_value=True): + has_default_value=True, containing_oneof=None): """The arguments are as described in the description of FieldDescriptor attributes above. @@ -396,6 +478,45 @@ class FieldDescriptor(DescriptorBase): self.enum_type = enum_type self.is_extension = is_extension self.extension_scope = extension_scope + self.containing_oneof = containing_oneof + if api_implementation.Type() == 'cpp': + if is_extension: + if api_implementation.Version() == 2: + # pylint: disable=protected-access + self._cdescriptor = ( + _message.Message._GetExtensionDescriptor(full_name)) + # pylint: enable=protected-access + else: + self._cdescriptor = cpp_message.GetExtensionDescriptor(full_name) + else: + if api_implementation.Version() == 2: + # pylint: disable=protected-access + self._cdescriptor = _message.Message._GetFieldDescriptor(full_name) + # pylint: enable=protected-access + else: + self._cdescriptor = cpp_message.GetFieldDescriptor(full_name) + else: + self._cdescriptor = None + + @staticmethod + def ProtoTypeToCppProtoType(proto_type): + """Converts from a Python proto type to a C++ Proto Type. + + The Python ProtocolBuffer classes specify both the 'Python' datatype and the + 'C++' datatype - and they're not the same. This helper method should + translate from one to another. + + Args: + proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*) + Returns: + descriptor.FieldDescriptor.CPPTYPE_*, the C++ type. + Raises: + TypeTransformationError: when the Python proto type isn't known. + """ + try: + return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type] + except KeyError: + raise TypeTransformationError('Unknown proto_type: %s' % proto_type) class EnumDescriptor(_NestedDescriptorBase): @@ -434,7 +555,7 @@ class EnumDescriptor(_NestedDescriptorBase): super(EnumDescriptor, self).__init__( options, 'EnumOptions', name, full_name, file, containing_type, serialized_start=serialized_start, - serialized_end=serialized_start) + serialized_end=serialized_end) self.values = values for value in self.values: @@ -442,9 +563,6 @@ class EnumDescriptor(_NestedDescriptorBase): self.values_by_name = dict((v.name, v) for v in values) self.values_by_number = dict((v.number, v) for v in values) - self._serialized_start = serialized_start - self._serialized_end = serialized_end - def CopyToProto(self, proto): """Copies this to a descriptor_pb2.EnumDescriptorProto. @@ -479,6 +597,29 @@ class EnumValueDescriptor(DescriptorBase): self.type = type +class OneofDescriptor(object): + """Descriptor for a oneof field. + + name: (str) Name of the oneof field. + full_name: (str) Full name of the oneof field, including package name. + index: (int) 0-based index giving the order of the oneof field inside + its containing type. + containing_type: (Descriptor) Descriptor of the protocol message + type that contains this field. Set by the Descriptor constructor + if we're passed into one. + fields: (list of FieldDescriptor) The list of field descriptors this + oneof can contain. + """ + + def __init__(self, name, full_name, index, containing_type, fields): + """Arguments are as described in the attribute description above.""" + self.name = name + self.full_name = full_name + self.index = index + self.containing_type = containing_type + self.fields = fields + + class ServiceDescriptor(_NestedDescriptorBase): """Descriptor for a service. @@ -557,20 +698,43 @@ class MethodDescriptor(DescriptorBase): class FileDescriptor(DescriptorBase): """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto. + Note that enum_types_by_name, extensions_by_name, and dependencies + fields are only set by the message_factory module, and not by the + generated proto code. + name: name of file, relative to root of source tree. package: name of the package serialized_pb: (str) Byte string of serialized descriptor_pb2.FileDescriptorProto. + dependencies: List of other FileDescriptors this FileDescriptor depends on. + message_types_by_name: Dict of message names of their descriptors. + enum_types_by_name: Dict of enum names and their descriptors. + extensions_by_name: Dict of extension names and their descriptors. """ - def __init__(self, name, package, options=None, serialized_pb=None): + def __init__(self, name, package, options=None, serialized_pb=None, + dependencies=None): """Constructor.""" super(FileDescriptor, self).__init__(options, 'FileOptions') + self.message_types_by_name = {} self.name = name self.package = package self.serialized_pb = serialized_pb + self.enum_types_by_name = {} + self.extensions_by_name = {} + self.dependencies = (dependencies or []) + + if (api_implementation.Type() == 'cpp' and + self.serialized_pb is not None): + if api_implementation.Version() == 2: + # pylint: disable=protected-access + _message.Message._BuildFile(self.serialized_pb) + # pylint: enable=protected-access + else: + cpp_message.BuildFile(self.serialized_pb) + def CopyToProto(self, proto): """Copies this to a descriptor_pb2.FileDescriptorProto. @@ -588,3 +752,98 @@ def _ParseOptions(message, string): """ message.ParseFromString(string) return message + + +def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True): + """Make a protobuf Descriptor given a DescriptorProto protobuf. + + Handles nested descriptors. Note that this is limited to the scope of defining + a message inside of another message. Composite fields can currently only be + resolved if the message is defined in the same scope as the field. + + Args: + desc_proto: The descriptor_pb2.DescriptorProto protobuf message. + package: Optional package name for the new message Descriptor (string). + build_file_if_cpp: Update the C++ descriptor pool if api matches. + Set to False on recursion, so no duplicates are created. + Returns: + A Descriptor for protobuf messages. + """ + if api_implementation.Type() == 'cpp' and build_file_if_cpp: + # The C++ implementation requires all descriptors to be backed by the same + # definition in the C++ descriptor pool. To do this, we build a + # FileDescriptorProto with the same definition as this descriptor and build + # it into the pool. + from google.protobuf import descriptor_pb2 + file_descriptor_proto = descriptor_pb2.FileDescriptorProto() + file_descriptor_proto.message_type.add().MergeFrom(desc_proto) + + # Generate a random name for this proto file to prevent conflicts with + # any imported ones. We need to specify a file name so BuildFile accepts + # our FileDescriptorProto, but it is not important what that file name + # is actually set to. + proto_name = str(uuid.uuid4()) + + if package: + file_descriptor_proto.name = os.path.join(package.replace('.', '/'), + proto_name + '.proto') + file_descriptor_proto.package = package + else: + file_descriptor_proto.name = proto_name + '.proto' + + if api_implementation.Version() == 2: + # pylint: disable=protected-access + _message.Message._BuildFile(file_descriptor_proto.SerializeToString()) + # pylint: enable=protected-access + else: + cpp_message.BuildFile(file_descriptor_proto.SerializeToString()) + + full_message_name = [desc_proto.name] + if package: full_message_name.insert(0, package) + + # Create Descriptors for enum types + enum_types = {} + for enum_proto in desc_proto.enum_type: + full_name = '.'.join(full_message_name + [enum_proto.name]) + enum_desc = EnumDescriptor( + enum_proto.name, full_name, None, [ + EnumValueDescriptor(enum_val.name, ii, enum_val.number) + for ii, enum_val in enumerate(enum_proto.value)]) + enum_types[full_name] = enum_desc + + # Create Descriptors for nested types + nested_types = {} + for nested_proto in desc_proto.nested_type: + full_name = '.'.join(full_message_name + [nested_proto.name]) + # Nested types are just those defined inside of the message, not all types + # used by fields in the message, so no loops are possible here. + nested_desc = MakeDescriptor(nested_proto, + package='.'.join(full_message_name), + build_file_if_cpp=False) + nested_types[full_name] = nested_desc + + fields = [] + for field_proto in desc_proto.field: + full_name = '.'.join(full_message_name + [field_proto.name]) + enum_desc = None + nested_desc = None + if field_proto.HasField('type_name'): + type_name = field_proto.type_name + full_type_name = '.'.join(full_message_name + + [type_name[type_name.rfind('.')+1:]]) + if full_type_name in nested_types: + nested_desc = nested_types[full_type_name] + elif full_type_name in enum_types: + enum_desc = enum_types[full_type_name] + # Else type_name references a non-local type, which isn't implemented + field = FieldDescriptor( + field_proto.name, full_name, field_proto.number - 1, + field_proto.number, field_proto.type, + FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type), + field_proto.label, None, nested_desc, enum_desc, None, False, None, + has_default_value=False) + fields.append(field) + + desc_name = '.'.join(full_message_name) + return Descriptor(desc_proto.name, desc_name, None, None, fields, + nested_types.values(), enum_types.values(), []) diff --git a/python/google/protobuf/descriptor_database.py b/python/google/protobuf/descriptor_database.py new file mode 100644 index 0000000..9f5a117 --- /dev/null +++ b/python/google/protobuf/descriptor_database.py @@ -0,0 +1,137 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Provides a container for DescriptorProtos.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + + +class Error(Exception): + pass + + +class DescriptorDatabaseConflictingDefinitionError(Error): + """Raised when a proto is added with the same name & different descriptor.""" + + +class DescriptorDatabase(object): + """A container accepting FileDescriptorProtos and maps DescriptorProtos.""" + + def __init__(self): + self._file_desc_protos_by_file = {} + self._file_desc_protos_by_symbol = {} + + def Add(self, file_desc_proto): + """Adds the FileDescriptorProto and its types to this database. + + Args: + file_desc_proto: The FileDescriptorProto to add. + Raises: + DescriptorDatabaseException: if an attempt is made to add a proto + with the same name but different definition than an exisiting + proto in the database. + """ + proto_name = file_desc_proto.name + if proto_name not in self._file_desc_protos_by_file: + self._file_desc_protos_by_file[proto_name] = file_desc_proto + elif self._file_desc_protos_by_file[proto_name] != file_desc_proto: + raise DescriptorDatabaseConflictingDefinitionError( + '%s already added, but with different descriptor.' % proto_name) + + package = file_desc_proto.package + for message in file_desc_proto.message_type: + self._file_desc_protos_by_symbol.update( + (name, file_desc_proto) for name in _ExtractSymbols(message, package)) + for enum in file_desc_proto.enum_type: + self._file_desc_protos_by_symbol[ + '.'.join((package, enum.name))] = file_desc_proto + + def FindFileByName(self, name): + """Finds the file descriptor proto by file name. + + Typically the file name is a relative path ending to a .proto file. The + proto with the given name will have to have been added to this database + using the Add method or else an error will be raised. + + Args: + name: The file name to find. + + Returns: + The file descriptor proto matching the name. + + Raises: + KeyError if no file by the given name was added. + """ + + return self._file_desc_protos_by_file[name] + + def FindFileContainingSymbol(self, symbol): + """Finds the file descriptor proto containing the specified symbol. + + The symbol should be a fully qualified name including the file descriptor's + package and any containing messages. Some examples: + + 'some.package.name.Message' + 'some.package.name.Message.NestedEnum' + + The file descriptor proto containing the specified symbol must be added to + this database using the Add method or else an error will be raised. + + Args: + symbol: The fully qualified symbol name. + + Returns: + The file descriptor proto containing the symbol. + + Raises: + KeyError if no file contains the specified symbol. + """ + + return self._file_desc_protos_by_symbol[symbol] + + +def _ExtractSymbols(desc_proto, package): + """Pulls out all the symbols from a descriptor proto. + + Args: + desc_proto: The proto to extract symbols from. + package: The package containing the descriptor type. + + Yields: + The fully qualified name found in the descriptor. + """ + + message_name = '.'.join((package, desc_proto.name)) + yield message_name + for nested_type in desc_proto.nested_type: + for symbol in _ExtractSymbols(nested_type, message_name): + yield symbol + for enum_type in desc_proto.enum_type: + yield '.'.join((message_name, enum_type.name)) diff --git a/python/google/protobuf/descriptor_pool.py b/python/google/protobuf/descriptor_pool.py new file mode 100644 index 0000000..372f458 --- /dev/null +++ b/python/google/protobuf/descriptor_pool.py @@ -0,0 +1,643 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Provides DescriptorPool to use as a container for proto2 descriptors. + +The DescriptorPool is used in conjection with a DescriptorDatabase to maintain +a collection of protocol buffer descriptors for use when dynamically creating +message types at runtime. + +For most applications protocol buffers should be used via modules generated by +the protocol buffer compiler tool. This should only be used when the type of +protocol buffers used in an application or library cannot be predetermined. + +Below is a straightforward example on how to use this class: + + pool = DescriptorPool() + file_descriptor_protos = [ ... ] + for file_descriptor_proto in file_descriptor_protos: + pool.Add(file_descriptor_proto) + my_message_descriptor = pool.FindMessageTypeByName('some.package.MessageType') + +The message descriptor can be used in conjunction with the message_factory +module in order to create a protocol buffer class that can be encoded and +decoded. + +If you want to get a Python class for the specified proto, use the +helper functions inside google.protobuf.message_factory +directly instead of this class. +""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +import sys + +from google.protobuf import descriptor +from google.protobuf import descriptor_database +from google.protobuf import text_encoding + + +def _NormalizeFullyQualifiedName(name): + """Remove leading period from fully-qualified type name. + + Due to b/13860351 in descriptor_database.py, types in the root namespace are + generated with a leading period. This function removes that prefix. + + Args: + name: A str, the fully-qualified symbol name. + + Returns: + A str, the normalized fully-qualified symbol name. + """ + return name.lstrip('.') + + +class DescriptorPool(object): + """A collection of protobufs dynamically constructed by descriptor protos.""" + + def __init__(self, descriptor_db=None): + """Initializes a Pool of proto buffs. + + The descriptor_db argument to the constructor is provided to allow + specialized file descriptor proto lookup code to be triggered on demand. An + example would be an implementation which will read and compile a file + specified in a call to FindFileByName() and not require the call to Add() + at all. Results from this database will be cached internally here as well. + + Args: + descriptor_db: A secondary source of file descriptors. + """ + + self._internal_db = descriptor_database.DescriptorDatabase() + self._descriptor_db = descriptor_db + self._descriptors = {} + self._enum_descriptors = {} + self._file_descriptors = {} + + def Add(self, file_desc_proto): + """Adds the FileDescriptorProto and its types to this pool. + + Args: + file_desc_proto: The FileDescriptorProto to add. + """ + + self._internal_db.Add(file_desc_proto) + + def AddDescriptor(self, desc): + """Adds a Descriptor to the pool, non-recursively. + + If the Descriptor contains nested messages or enums, the caller must + explicitly register them. This method also registers the FileDescriptor + associated with the message. + + Args: + desc: A Descriptor. + """ + if not isinstance(desc, descriptor.Descriptor): + raise TypeError('Expected instance of descriptor.Descriptor.') + + self._descriptors[desc.full_name] = desc + self.AddFileDescriptor(desc.file) + + def AddEnumDescriptor(self, enum_desc): + """Adds an EnumDescriptor to the pool. + + This method also registers the FileDescriptor associated with the message. + + Args: + enum_desc: An EnumDescriptor. + """ + + if not isinstance(enum_desc, descriptor.EnumDescriptor): + raise TypeError('Expected instance of descriptor.EnumDescriptor.') + + self._enum_descriptors[enum_desc.full_name] = enum_desc + self.AddFileDescriptor(enum_desc.file) + + def AddFileDescriptor(self, file_desc): + """Adds a FileDescriptor to the pool, non-recursively. + + If the FileDescriptor contains messages or enums, the caller must explicitly + register them. + + Args: + file_desc: A FileDescriptor. + """ + + if not isinstance(file_desc, descriptor.FileDescriptor): + raise TypeError('Expected instance of descriptor.FileDescriptor.') + self._file_descriptors[file_desc.name] = file_desc + + def FindFileByName(self, file_name): + """Gets a FileDescriptor by file name. + + Args: + file_name: The path to the file to get a descriptor for. + + Returns: + A FileDescriptor for the named file. + + Raises: + KeyError: if the file can not be found in the pool. + """ + + try: + return self._file_descriptors[file_name] + except KeyError: + pass + + try: + file_proto = self._internal_db.FindFileByName(file_name) + except KeyError: + _, error, _ = sys.exc_info() #PY25 compatible for GAE. + if self._descriptor_db: + file_proto = self._descriptor_db.FindFileByName(file_name) + else: + raise error + if not file_proto: + raise KeyError('Cannot find a file named %s' % file_name) + return self._ConvertFileProtoToFileDescriptor(file_proto) + + def FindFileContainingSymbol(self, symbol): + """Gets the FileDescriptor for the file containing the specified symbol. + + Args: + symbol: The name of the symbol to search for. + + Returns: + A FileDescriptor that contains the specified symbol. + + Raises: + KeyError: if the file can not be found in the pool. + """ + + symbol = _NormalizeFullyQualifiedName(symbol) + try: + return self._descriptors[symbol].file + except KeyError: + pass + + try: + return self._enum_descriptors[symbol].file + except KeyError: + pass + + try: + file_proto = self._internal_db.FindFileContainingSymbol(symbol) + except KeyError: + _, error, _ = sys.exc_info() #PY25 compatible for GAE. + if self._descriptor_db: + file_proto = self._descriptor_db.FindFileContainingSymbol(symbol) + else: + raise error + if not file_proto: + raise KeyError('Cannot find a file containing %s' % symbol) + return self._ConvertFileProtoToFileDescriptor(file_proto) + + def FindMessageTypeByName(self, full_name): + """Loads the named descriptor from the pool. + + Args: + full_name: The full name of the descriptor to load. + + Returns: + The descriptor for the named type. + """ + + full_name = _NormalizeFullyQualifiedName(full_name) + if full_name not in self._descriptors: + self.FindFileContainingSymbol(full_name) + return self._descriptors[full_name] + + def FindEnumTypeByName(self, full_name): + """Loads the named enum descriptor from the pool. + + Args: + full_name: The full name of the enum descriptor to load. + + Returns: + The enum descriptor for the named type. + """ + + full_name = _NormalizeFullyQualifiedName(full_name) + if full_name not in self._enum_descriptors: + self.FindFileContainingSymbol(full_name) + return self._enum_descriptors[full_name] + + def _ConvertFileProtoToFileDescriptor(self, file_proto): + """Creates a FileDescriptor from a proto or returns a cached copy. + + This method also has the side effect of loading all the symbols found in + the file into the appropriate dictionaries in the pool. + + Args: + file_proto: The proto to convert. + + Returns: + A FileDescriptor matching the passed in proto. + """ + + if file_proto.name not in self._file_descriptors: + built_deps = list(self._GetDeps(file_proto.dependency)) + direct_deps = [self.FindFileByName(n) for n in file_proto.dependency] + + file_descriptor = descriptor.FileDescriptor( + name=file_proto.name, + package=file_proto.package, + options=file_proto.options, + serialized_pb=file_proto.SerializeToString(), + dependencies=direct_deps) + scope = {} + + # This loop extracts all the message and enum types from all the + # dependencoes of the file_proto. This is necessary to create the + # scope of available message types when defining the passed in + # file proto. + for dependency in built_deps: + scope.update(self._ExtractSymbols( + dependency.message_types_by_name.values())) + scope.update((_PrefixWithDot(enum.full_name), enum) + for enum in dependency.enum_types_by_name.values()) + + for message_type in file_proto.message_type: + message_desc = self._ConvertMessageDescriptor( + message_type, file_proto.package, file_descriptor, scope) + file_descriptor.message_types_by_name[message_desc.name] = message_desc + + for enum_type in file_proto.enum_type: + file_descriptor.enum_types_by_name[enum_type.name] = ( + self._ConvertEnumDescriptor(enum_type, file_proto.package, + file_descriptor, None, scope)) + + for index, extension_proto in enumerate(file_proto.extension): + extension_desc = self.MakeFieldDescriptor( + extension_proto, file_proto.package, index, is_extension=True) + extension_desc.containing_type = self._GetTypeFromScope( + file_descriptor.package, extension_proto.extendee, scope) + self.SetFieldType(extension_proto, extension_desc, + file_descriptor.package, scope) + file_descriptor.extensions_by_name[extension_desc.name] = extension_desc + + for desc_proto in file_proto.message_type: + self.SetAllFieldTypes(file_proto.package, desc_proto, scope) + + if file_proto.package: + desc_proto_prefix = _PrefixWithDot(file_proto.package) + else: + desc_proto_prefix = '' + + for desc_proto in file_proto.message_type: + desc = self._GetTypeFromScope(desc_proto_prefix, desc_proto.name, scope) + file_descriptor.message_types_by_name[desc_proto.name] = desc + self.Add(file_proto) + self._file_descriptors[file_proto.name] = file_descriptor + + return self._file_descriptors[file_proto.name] + + def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None, + scope=None): + """Adds the proto to the pool in the specified package. + + Args: + desc_proto: The descriptor_pb2.DescriptorProto protobuf message. + package: The package the proto should be located in. + file_desc: The file containing this message. + scope: Dict mapping short and full symbols to message and enum types. + + Returns: + The added descriptor. + """ + + if package: + desc_name = '.'.join((package, desc_proto.name)) + else: + desc_name = desc_proto.name + + if file_desc is None: + file_name = None + else: + file_name = file_desc.name + + if scope is None: + scope = {} + + nested = [ + self._ConvertMessageDescriptor(nested, desc_name, file_desc, scope) + for nested in desc_proto.nested_type] + enums = [ + self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope) + for enum in desc_proto.enum_type] + fields = [self.MakeFieldDescriptor(field, desc_name, index) + for index, field in enumerate(desc_proto.field)] + extensions = [ + self.MakeFieldDescriptor(extension, desc_name, index, is_extension=True) + for index, extension in enumerate(desc_proto.extension)] + oneofs = [ + descriptor.OneofDescriptor(desc.name, '.'.join((desc_name, desc.name)), + index, None, []) + for index, desc in enumerate(desc_proto.oneof_decl)] + extension_ranges = [(r.start, r.end) for r in desc_proto.extension_range] + if extension_ranges: + is_extendable = True + else: + is_extendable = False + desc = descriptor.Descriptor( + name=desc_proto.name, + full_name=desc_name, + filename=file_name, + containing_type=None, + fields=fields, + oneofs=oneofs, + nested_types=nested, + enum_types=enums, + extensions=extensions, + options=desc_proto.options, + is_extendable=is_extendable, + extension_ranges=extension_ranges, + file=file_desc, + serialized_start=None, + serialized_end=None) + for nested in desc.nested_types: + nested.containing_type = desc + for enum in desc.enum_types: + enum.containing_type = desc + for field_index, field_desc in enumerate(desc_proto.field): + if field_desc.HasField('oneof_index'): + oneof_index = field_desc.oneof_index + oneofs[oneof_index].fields.append(fields[field_index]) + fields[field_index].containing_oneof = oneofs[oneof_index] + + scope[_PrefixWithDot(desc_name)] = desc + self._descriptors[desc_name] = desc + return desc + + def _ConvertEnumDescriptor(self, enum_proto, package=None, file_desc=None, + containing_type=None, scope=None): + """Make a protobuf EnumDescriptor given an EnumDescriptorProto protobuf. + + Args: + enum_proto: The descriptor_pb2.EnumDescriptorProto protobuf message. + package: Optional package name for the new message EnumDescriptor. + file_desc: The file containing the enum descriptor. + containing_type: The type containing this enum. + scope: Scope containing available types. + + Returns: + The added descriptor + """ + + if package: + enum_name = '.'.join((package, enum_proto.name)) + else: + enum_name = enum_proto.name + + if file_desc is None: + file_name = None + else: + file_name = file_desc.name + + values = [self._MakeEnumValueDescriptor(value, index) + for index, value in enumerate(enum_proto.value)] + desc = descriptor.EnumDescriptor(name=enum_proto.name, + full_name=enum_name, + filename=file_name, + file=file_desc, + values=values, + containing_type=containing_type, + options=enum_proto.options) + scope['.%s' % enum_name] = desc + self._enum_descriptors[enum_name] = desc + return desc + + def MakeFieldDescriptor(self, field_proto, message_name, index, + is_extension=False): + """Creates a field descriptor from a FieldDescriptorProto. + + For message and enum type fields, this method will do a look up + in the pool for the appropriate descriptor for that type. If it + is unavailable, it will fall back to the _source function to + create it. If this type is still unavailable, construction will + fail. + + Args: + field_proto: The proto describing the field. + message_name: The name of the containing message. + index: Index of the field + is_extension: Indication that this field is for an extension. + + Returns: + An initialized FieldDescriptor object + """ + + if message_name: + full_name = '.'.join((message_name, field_proto.name)) + else: + full_name = field_proto.name + + return descriptor.FieldDescriptor( + name=field_proto.name, + full_name=full_name, + index=index, + number=field_proto.number, + type=field_proto.type, + cpp_type=None, + message_type=None, + enum_type=None, + containing_type=None, + label=field_proto.label, + has_default_value=False, + default_value=None, + is_extension=is_extension, + extension_scope=None, + options=field_proto.options) + + def SetAllFieldTypes(self, package, desc_proto, scope): + """Sets all the descriptor's fields's types. + + This method also sets the containing types on any extensions. + + Args: + package: The current package of desc_proto. + desc_proto: The message descriptor to update. + scope: Enclosing scope of available types. + """ + + package = _PrefixWithDot(package) + + main_desc = self._GetTypeFromScope(package, desc_proto.name, scope) + + if package == '.': + nested_package = _PrefixWithDot(desc_proto.name) + else: + nested_package = '.'.join([package, desc_proto.name]) + + for field_proto, field_desc in zip(desc_proto.field, main_desc.fields): + self.SetFieldType(field_proto, field_desc, nested_package, scope) + + for extension_proto, extension_desc in ( + zip(desc_proto.extension, main_desc.extensions)): + extension_desc.containing_type = self._GetTypeFromScope( + nested_package, extension_proto.extendee, scope) + self.SetFieldType(extension_proto, extension_desc, nested_package, scope) + + for nested_type in desc_proto.nested_type: + self.SetAllFieldTypes(nested_package, nested_type, scope) + + def SetFieldType(self, field_proto, field_desc, package, scope): + """Sets the field's type, cpp_type, message_type and enum_type. + + Args: + field_proto: Data about the field in proto format. + field_desc: The descriptor to modiy. + package: The package the field's container is in. + scope: Enclosing scope of available types. + """ + if field_proto.type_name: + desc = self._GetTypeFromScope(package, field_proto.type_name, scope) + else: + desc = None + + if not field_proto.HasField('type'): + if isinstance(desc, descriptor.Descriptor): + field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE + else: + field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM + + field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType( + field_proto.type) + + if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE + or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP): + field_desc.message_type = desc + + if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: + field_desc.enum_type = desc + + if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED: + field_desc.has_default_value = False + field_desc.default_value = [] + elif field_proto.HasField('default_value'): + field_desc.has_default_value = True + if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or + field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT): + field_desc.default_value = float(field_proto.default_value) + elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING: + field_desc.default_value = field_proto.default_value + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL: + field_desc.default_value = field_proto.default_value.lower() == 'true' + elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: + field_desc.default_value = field_desc.enum_type.values_by_name[ + field_proto.default_value].index + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES: + field_desc.default_value = text_encoding.CUnescape( + field_proto.default_value) + else: + field_desc.default_value = int(field_proto.default_value) + else: + field_desc.has_default_value = False + field_desc.default_value = None + + field_desc.type = field_proto.type + + def _MakeEnumValueDescriptor(self, value_proto, index): + """Creates a enum value descriptor object from a enum value proto. + + Args: + value_proto: The proto describing the enum value. + index: The index of the enum value. + + Returns: + An initialized EnumValueDescriptor object. + """ + + return descriptor.EnumValueDescriptor( + name=value_proto.name, + index=index, + number=value_proto.number, + options=value_proto.options, + type=None) + + def _ExtractSymbols(self, descriptors): + """Pulls out all the symbols from descriptor protos. + + Args: + descriptors: The messages to extract descriptors from. + Yields: + A two element tuple of the type name and descriptor object. + """ + + for desc in descriptors: + yield (_PrefixWithDot(desc.full_name), desc) + for symbol in self._ExtractSymbols(desc.nested_types): + yield symbol + for enum in desc.enum_types: + yield (_PrefixWithDot(enum.full_name), enum) + + def _GetDeps(self, dependencies): + """Recursively finds dependencies for file protos. + + Args: + dependencies: The names of the files being depended on. + + Yields: + Each direct and indirect dependency. + """ + + for dependency in dependencies: + dep_desc = self.FindFileByName(dependency) + yield dep_desc + for parent_dep in dep_desc.dependencies: + yield parent_dep + + def _GetTypeFromScope(self, package, type_name, scope): + """Finds a given type name in the current scope. + + Args: + package: The package the proto should be located in. + type_name: The name of the type to be found in the scope. + scope: Dict mapping short and full symbols to message and enum types. + + Returns: + The descriptor for the requested type. + """ + if type_name not in scope: + components = _PrefixWithDot(package).split('.') + while components: + possible_match = '.'.join(components + [type_name]) + if possible_match in scope: + type_name = possible_match + break + else: + components.pop(-1) + return scope[type_name] + + +def _PrefixWithDot(name): + return name if name.startswith('.') else '.%s' % name diff --git a/python/google/protobuf/internal/api_implementation.cc b/python/google/protobuf/internal/api_implementation.cc new file mode 100644 index 0000000..ad6fd9c --- /dev/null +++ b/python/google/protobuf/internal/api_implementation.cc @@ -0,0 +1,139 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +#include + +namespace google { +namespace protobuf { +namespace python { + +// Version constant. +// This is either 0 for python, 1 for CPP V1, 2 for CPP V2. +// +// 0 is default and is equivalent to +// PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python +// +// 1 is set with -DPYTHON_PROTO2_CPP_IMPL_V1 and is equivalent to +// PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp +// and +// PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=1 +// +// 2 is set with -DPYTHON_PROTO2_CPP_IMPL_V2 and is equivalent to +// PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp +// and +// PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2 +#ifdef PYTHON_PROTO2_CPP_IMPL_V1 +#if PY_MAJOR_VERSION >= 3 +#error "PYTHON_PROTO2_CPP_IMPL_V1 is not supported under Python 3." +#endif +static int kImplVersion = 1; +#else +#ifdef PYTHON_PROTO2_CPP_IMPL_V2 +static int kImplVersion = 2; +#else +#ifdef PYTHON_PROTO2_PYTHON_IMPL +static int kImplVersion = 0; +#else + +// The defaults are set here. Python 3 uses the fast C++ APIv2 by default. +// Python 2 still uses the Python version by default until some compatibility +// issues can be worked around. +#if PY_MAJOR_VERSION >= 3 +static int kImplVersion = 2; +#else +static int kImplVersion = 0; +#endif + +#endif // PYTHON_PROTO2_PYTHON_IMPL +#endif // PYTHON_PROTO2_CPP_IMPL_V2 +#endif // PYTHON_PROTO2_CPP_IMPL_V1 + +static const char* kImplVersionName = "api_version"; + +static const char* kModuleName = "_api_implementation"; +static const char kModuleDocstring[] = +"_api_implementation is a module that exposes compile-time constants that\n" +"determine the default API implementation to use for Python proto2.\n" +"\n" +"It complements api_implementation.py by setting defaults using compile-time\n" +"constants defined in C, such that one can set defaults at compilation\n" +"(e.g. with blaze flag --copt=-DPYTHON_PROTO2_CPP_IMPL_V2)."; + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef _module = { + PyModuleDef_HEAD_INIT, + kModuleName, + kModuleDocstring, + -1, + NULL, + NULL, + NULL, + NULL, + NULL +}; +#define INITFUNC PyInit__api_implementation +#define INITFUNC_ERRORVAL NULL +#else +#define INITFUNC init_api_implementation +#define INITFUNC_ERRORVAL +#endif + +extern "C" { + PyMODINIT_FUNC INITFUNC() { +#if PY_MAJOR_VERSION >= 3 + PyObject *module = PyModule_Create(&_module); +#else + PyObject *module = Py_InitModule3( + const_cast(kModuleName), + NULL, + const_cast(kModuleDocstring)); +#endif + if (module == NULL) { + return INITFUNC_ERRORVAL; + } + + // Adds the module variable "api_version". + if (PyModule_AddIntConstant( + module, + const_cast(kImplVersionName), + kImplVersion)) +#if PY_MAJOR_VERSION < 3 + return; +#else + { Py_DECREF(module); return NULL; } + + return module; +#endif + } +} + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py new file mode 100755 index 0000000..cbb8574 --- /dev/null +++ b/python/google/protobuf/internal/api_implementation.py @@ -0,0 +1,89 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Determine which implementation of the protobuf API is used in this process. +""" + +import os +import sys + +try: + # pylint: disable=g-import-not-at-top + from google.protobuf.internal import _api_implementation + # The compile-time constants in the _api_implementation module can be used to + # switch to a certain implementation of the Python API at build time. + _api_version = _api_implementation.api_version + del _api_implementation +except ImportError: + _api_version = 0 + +_default_implementation_type = ( + 'python' if _api_version == 0 else 'cpp') +_default_version_str = ( + '1' if _api_version <= 1 else '2') + +# This environment variable can be used to switch to a certain implementation +# of the Python API, overriding the compile-time constants in the +# _api_implementation module. Right now only 'python' and 'cpp' are valid +# values. Any other value will be ignored. +_implementation_type = os.getenv('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION', + _default_implementation_type) + +if _implementation_type != 'python': + _implementation_type = 'cpp' + +# This environment variable can be used to switch between the two +# 'cpp' implementations, overriding the compile-time constants in the +# _api_implementation module. Right now only 1 and 2 are valid values. Any other +# value will be ignored. +_implementation_version_str = os.getenv( + 'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', + _default_version_str) + +if _implementation_version_str not in ('1', '2'): + raise ValueError( + "unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: '" + + _implementation_version_str + "' (supported versions: 1, 2)" + ) + +_implementation_version = int(_implementation_version_str) + + +# Usage of this function is discouraged. Clients shouldn't care which +# implementation of the API is in use. Note that there is no guarantee +# that differences between APIs will be maintained. +# Please don't use this function if possible. +def Type(): + return _implementation_type + + +# See comment on 'Type' above. +def Version(): + return _implementation_version diff --git a/python/google/protobuf/internal/api_implementation_default_test.py b/python/google/protobuf/internal/api_implementation_default_test.py new file mode 100644 index 0000000..b2b4128 --- /dev/null +++ b/python/google/protobuf/internal/api_implementation_default_test.py @@ -0,0 +1,63 @@ +#! /usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Test that the api_implementation defaults are what we expect.""" + +import os +import sys +# Clear environment implementation settings before the google3 imports. +os.environ.pop('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION', None) +os.environ.pop('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', None) + +# pylint: disable=g-import-not-at-top +from google.apputils import basetest +from google.protobuf.internal import api_implementation + + +class ApiImplementationDefaultTest(basetest.TestCase): + + if sys.version_info.major <= 2: + + def testThatPythonIsTheDefault(self): + """If -DPYTHON_PROTO_*IMPL* was given at build time, this may fail.""" + self.assertEqual('python', api_implementation.Type()) + + else: + + def testThatCppApiV2IsTheDefault(self): + """If -DPYTHON_PROTO_*IMPL* was given at build time, this may fail.""" + self.assertEqual('cpp', api_implementation.Type()) + self.assertEqual(2, api_implementation.Version()) + + +if __name__ == '__main__': + basetest.main() diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py index 5cc7d6d..5797e81 100755 --- a/python/google/protobuf/internal/containers.py +++ b/python/google/protobuf/internal/containers.py @@ -72,9 +72,20 @@ class BaseContainer(object): # The concrete classes should define __eq__. return not self == other + def __hash__(self): + raise TypeError('unhashable object') + def __repr__(self): return repr(self._values) + def sort(self, *args, **kwargs): + # Continue to support the old sort_function keyword argument. + # This is expected to be a rare occurrence, so use LBYL to avoid + # the overhead of actually catching KeyError. + if 'sort_function' in kwargs: + kwargs['cmp'] = kwargs.pop('sort_function') + self._values.sort(*args, **kwargs) + class RepeatedScalarFieldContainer(BaseContainer): @@ -97,15 +108,13 @@ class RepeatedScalarFieldContainer(BaseContainer): def append(self, value): """Appends an item to the list. Similar to list.append().""" - self._type_checker.CheckValue(value) - self._values.append(value) + self._values.append(self._type_checker.CheckValue(value)) if not self._message_listener.dirty: self._message_listener.Modified() def insert(self, key, value): """Inserts the item at the specified position. Similar to list.insert().""" - self._type_checker.CheckValue(value) - self._values.insert(key, value) + self._values.insert(key, self._type_checker.CheckValue(value)) if not self._message_listener.dirty: self._message_listener.Modified() @@ -116,8 +125,7 @@ class RepeatedScalarFieldContainer(BaseContainer): new_values = [] for elem in elem_seq: - self._type_checker.CheckValue(elem) - new_values.append(elem) + new_values.append(self._type_checker.CheckValue(elem)) self._values.extend(new_values) self._message_listener.Modified() @@ -135,9 +143,13 @@ class RepeatedScalarFieldContainer(BaseContainer): def __setitem__(self, key, value): """Sets the item on the specified position.""" - self._type_checker.CheckValue(value) - self._values[key] = value - self._message_listener.Modified() + if isinstance(key, slice): # PY3 + if key.step is not None: + raise ValueError('Extended slices not supported') + self.__setslice__(key.start, key.stop, value) + else: + self._values[key] = self._type_checker.CheckValue(value) + self._message_listener.Modified() def __getslice__(self, start, stop): """Retrieves the subset of items from between the specified indices.""" @@ -147,8 +159,7 @@ class RepeatedScalarFieldContainer(BaseContainer): """Sets the subset of items from between the specified indices.""" new_values = [] for value in values: - self._type_checker.CheckValue(value) - new_values.append(value) + new_values.append(self._type_checker.CheckValue(value)) self._values[start:stop] = new_values self._message_listener.Modified() @@ -198,28 +209,42 @@ class RepeatedCompositeFieldContainer(BaseContainer): super(RepeatedCompositeFieldContainer, self).__init__(message_listener) self._message_descriptor = message_descriptor - def add(self): - new_element = self._message_descriptor._concrete_class() + def add(self, **kwargs): + """Adds a new element at the end of the list and returns it. Keyword + arguments may be used to initialize the element. + """ + new_element = self._message_descriptor._concrete_class(**kwargs) new_element._SetListener(self._message_listener) self._values.append(new_element) if not self._message_listener.dirty: self._message_listener.Modified() return new_element - def MergeFrom(self, other): - """Appends the contents of another repeated field of the same type to this - one, copying each individual message. + def extend(self, elem_seq): + """Extends by appending the given sequence of elements of the same type + as this one, copying each individual message. """ message_class = self._message_descriptor._concrete_class listener = self._message_listener values = self._values - for message in other._values: + for message in elem_seq: new_element = message_class() new_element._SetListener(listener) new_element.MergeFrom(message) values.append(new_element) listener.Modified() + def MergeFrom(self, other): + """Appends the contents of another repeated field of the same type to this + one, copying each individual message. + """ + self.extend(other._values) + + def remove(self, elem): + """Removes an item from the list. Similar to list.remove().""" + self._values.remove(elem) + self._message_listener.Modified() + def __getslice__(self, start, stop): """Retrieves the subset of items from between the specified indices.""" return self._values[start:stop] diff --git a/python/google/protobuf/internal/cpp_message.py b/python/google/protobuf/internal/cpp_message.py new file mode 100755 index 0000000..8eb38ca --- /dev/null +++ b/python/google/protobuf/internal/cpp_message.py @@ -0,0 +1,663 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Contains helper functions used to create protocol message classes from +Descriptor objects at runtime backed by the protocol buffer C++ API. +""" + +__author__ = 'petar@google.com (Petar Petrov)' + +import copy_reg +import operator +from google.protobuf.internal import _net_proto2___python +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import message + + +_LABEL_REPEATED = _net_proto2___python.LABEL_REPEATED +_LABEL_OPTIONAL = _net_proto2___python.LABEL_OPTIONAL +_CPPTYPE_MESSAGE = _net_proto2___python.CPPTYPE_MESSAGE +_TYPE_MESSAGE = _net_proto2___python.TYPE_MESSAGE + + +def GetDescriptorPool(): + """Creates a new DescriptorPool C++ object.""" + return _net_proto2___python.NewCDescriptorPool() + + +_pool = GetDescriptorPool() + + +def GetFieldDescriptor(full_field_name): + """Searches for a field descriptor given a full field name.""" + return _pool.FindFieldByName(full_field_name) + + +def BuildFile(content): + """Registers a new proto file in the underlying C++ descriptor pool.""" + _net_proto2___python.BuildFile(content) + + +def GetExtensionDescriptor(full_extension_name): + """Searches for extension descriptor given a full field name.""" + return _pool.FindExtensionByName(full_extension_name) + + +def NewCMessage(full_message_name): + """Creates a new C++ protocol message by its name.""" + return _net_proto2___python.NewCMessage(full_message_name) + + +def ScalarProperty(cdescriptor): + """Returns a scalar property for the given descriptor.""" + + def Getter(self): + return self._cmsg.GetScalar(cdescriptor) + + def Setter(self, value): + self._cmsg.SetScalar(cdescriptor, value) + + return property(Getter, Setter) + + +def CompositeProperty(cdescriptor, message_type): + """Returns a Python property the given composite field.""" + + def Getter(self): + sub_message = self._composite_fields.get(cdescriptor.name, None) + if sub_message is None: + cmessage = self._cmsg.NewSubMessage(cdescriptor) + sub_message = message_type._concrete_class(__cmessage=cmessage) + self._composite_fields[cdescriptor.name] = sub_message + return sub_message + + return property(Getter) + + +class RepeatedScalarContainer(object): + """Container for repeated scalar fields.""" + + __slots__ = ['_message', '_cfield_descriptor', '_cmsg'] + + def __init__(self, msg, cfield_descriptor): + self._message = msg + self._cmsg = msg._cmsg + self._cfield_descriptor = cfield_descriptor + + def append(self, value): + self._cmsg.AddRepeatedScalar( + self._cfield_descriptor, value) + + def extend(self, sequence): + for element in sequence: + self.append(element) + + def insert(self, key, value): + values = self[slice(None, None, None)] + values.insert(key, value) + self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, values) + + def remove(self, value): + values = self[slice(None, None, None)] + values.remove(value) + self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, values) + + def __setitem__(self, key, value): + values = self[slice(None, None, None)] + values[key] = value + self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, values) + + def __getitem__(self, key): + return self._cmsg.GetRepeatedScalar(self._cfield_descriptor, key) + + def __delitem__(self, key): + self._cmsg.DeleteRepeatedField(self._cfield_descriptor, key) + + def __len__(self): + return len(self[slice(None, None, None)]) + + def __eq__(self, other): + if self is other: + return True + if not operator.isSequenceType(other): + raise TypeError( + 'Can only compare repeated scalar fields against sequences.') + # We are presumably comparing against some other sequence type. + return other == self[slice(None, None, None)] + + def __ne__(self, other): + return not self == other + + def __hash__(self): + raise TypeError('unhashable object') + + def sort(self, *args, **kwargs): + # Maintain compatibility with the previous interface. + if 'sort_function' in kwargs: + kwargs['cmp'] = kwargs.pop('sort_function') + self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, + sorted(self, *args, **kwargs)) + + +def RepeatedScalarProperty(cdescriptor): + """Returns a Python property the given repeated scalar field.""" + + def Getter(self): + container = self._composite_fields.get(cdescriptor.name, None) + if container is None: + container = RepeatedScalarContainer(self, cdescriptor) + self._composite_fields[cdescriptor.name] = container + return container + + def Setter(self, new_value): + raise AttributeError('Assignment not allowed to repeated field ' + '"%s" in protocol message object.' % cdescriptor.name) + + doc = 'Magic attribute generated for "%s" proto field.' % cdescriptor.name + return property(Getter, Setter, doc=doc) + + +class RepeatedCompositeContainer(object): + """Container for repeated composite fields.""" + + __slots__ = ['_message', '_subclass', '_cfield_descriptor', '_cmsg'] + + def __init__(self, msg, cfield_descriptor, subclass): + self._message = msg + self._cmsg = msg._cmsg + self._subclass = subclass + self._cfield_descriptor = cfield_descriptor + + def add(self, **kwargs): + cmessage = self._cmsg.AddMessage(self._cfield_descriptor) + return self._subclass(__cmessage=cmessage, __owner=self._message, **kwargs) + + def extend(self, elem_seq): + """Extends by appending the given sequence of elements of the same type + as this one, copying each individual message. + """ + for message in elem_seq: + self.add().MergeFrom(message) + + def remove(self, value): + # TODO(protocol-devel): This is inefficient as it needs to generate a + # message pointer for each message only to do index(). Move this to a C++ + # extension function. + self.__delitem__(self[slice(None, None, None)].index(value)) + + def MergeFrom(self, other): + for message in other[:]: + self.add().MergeFrom(message) + + def __getitem__(self, key): + cmessages = self._cmsg.GetRepeatedMessage( + self._cfield_descriptor, key) + subclass = self._subclass + if not isinstance(cmessages, list): + return subclass(__cmessage=cmessages, __owner=self._message) + + return [subclass(__cmessage=m, __owner=self._message) for m in cmessages] + + def __delitem__(self, key): + self._cmsg.DeleteRepeatedField( + self._cfield_descriptor, key) + + def __len__(self): + return self._cmsg.FieldLength(self._cfield_descriptor) + + def __eq__(self, other): + """Compares the current instance with another one.""" + if self is other: + return True + if not isinstance(other, self.__class__): + raise TypeError('Can only compare repeated composite fields against ' + 'other repeated composite fields.') + messages = self[slice(None, None, None)] + other_messages = other[slice(None, None, None)] + return messages == other_messages + + def __hash__(self): + raise TypeError('unhashable object') + + def sort(self, cmp=None, key=None, reverse=False, **kwargs): + # Maintain compatibility with the old interface. + if cmp is None and 'sort_function' in kwargs: + cmp = kwargs.pop('sort_function') + + # The cmp function, if provided, is passed the results of the key function, + # so we only need to wrap one of them. + if key is None: + index_key = self.__getitem__ + else: + index_key = lambda i: key(self[i]) + + # Sort the list of current indexes by the underlying object. + indexes = range(len(self)) + indexes.sort(cmp=cmp, key=index_key, reverse=reverse) + + # Apply the transposition. + for dest, src in enumerate(indexes): + if dest == src: + continue + self._cmsg.SwapRepeatedFieldElements(self._cfield_descriptor, dest, src) + # Don't swap the same value twice. + indexes[src] = src + + +def RepeatedCompositeProperty(cdescriptor, message_type): + """Returns a Python property for the given repeated composite field.""" + + def Getter(self): + container = self._composite_fields.get(cdescriptor.name, None) + if container is None: + container = RepeatedCompositeContainer( + self, cdescriptor, message_type._concrete_class) + self._composite_fields[cdescriptor.name] = container + return container + + def Setter(self, new_value): + raise AttributeError('Assignment not allowed to repeated field ' + '"%s" in protocol message object.' % cdescriptor.name) + + doc = 'Magic attribute generated for "%s" proto field.' % cdescriptor.name + return property(Getter, Setter, doc=doc) + + +class ExtensionDict(object): + """Extension dictionary added to each protocol message.""" + + def __init__(self, msg): + self._message = msg + self._cmsg = msg._cmsg + self._values = {} + + def __setitem__(self, extension, value): + from google.protobuf import descriptor + if not isinstance(extension, descriptor.FieldDescriptor): + raise KeyError('Bad extension %r.' % (extension,)) + cdescriptor = extension._cdescriptor + if (cdescriptor.label != _LABEL_OPTIONAL or + cdescriptor.cpp_type == _CPPTYPE_MESSAGE): + raise TypeError('Extension %r is repeated and/or a composite type.' % ( + extension.full_name,)) + self._cmsg.SetScalar(cdescriptor, value) + self._values[extension] = value + + def __getitem__(self, extension): + from google.protobuf import descriptor + if not isinstance(extension, descriptor.FieldDescriptor): + raise KeyError('Bad extension %r.' % (extension,)) + + cdescriptor = extension._cdescriptor + if (cdescriptor.label != _LABEL_REPEATED and + cdescriptor.cpp_type != _CPPTYPE_MESSAGE): + return self._cmsg.GetScalar(cdescriptor) + + ext = self._values.get(extension, None) + if ext is not None: + return ext + + ext = self._CreateNewHandle(extension) + self._values[extension] = ext + return ext + + def ClearExtension(self, extension): + from google.protobuf import descriptor + if not isinstance(extension, descriptor.FieldDescriptor): + raise KeyError('Bad extension %r.' % (extension,)) + self._cmsg.ClearFieldByDescriptor(extension._cdescriptor) + if extension in self._values: + del self._values[extension] + + def HasExtension(self, extension): + from google.protobuf import descriptor + if not isinstance(extension, descriptor.FieldDescriptor): + raise KeyError('Bad extension %r.' % (extension,)) + return self._cmsg.HasFieldByDescriptor(extension._cdescriptor) + + def _FindExtensionByName(self, name): + """Tries to find a known extension with the specified name. + + Args: + name: Extension full name. + + Returns: + Extension field descriptor. + """ + return self._message._extensions_by_name.get(name, None) + + def _CreateNewHandle(self, extension): + cdescriptor = extension._cdescriptor + if (cdescriptor.label != _LABEL_REPEATED and + cdescriptor.cpp_type == _CPPTYPE_MESSAGE): + cmessage = self._cmsg.NewSubMessage(cdescriptor) + return extension.message_type._concrete_class(__cmessage=cmessage) + + if cdescriptor.label == _LABEL_REPEATED: + if cdescriptor.cpp_type == _CPPTYPE_MESSAGE: + return RepeatedCompositeContainer( + self._message, cdescriptor, extension.message_type._concrete_class) + else: + return RepeatedScalarContainer(self._message, cdescriptor) + # This shouldn't happen! + assert False + return None + + +def NewMessage(bases, message_descriptor, dictionary): + """Creates a new protocol message *class*.""" + _AddClassAttributesForNestedExtensions(message_descriptor, dictionary) + _AddEnumValues(message_descriptor, dictionary) + _AddDescriptors(message_descriptor, dictionary) + return bases + + +def InitMessage(message_descriptor, cls): + """Constructs a new message instance (called before instance's __init__).""" + cls._extensions_by_name = {} + _AddInitMethod(message_descriptor, cls) + _AddMessageMethods(message_descriptor, cls) + _AddPropertiesForExtensions(message_descriptor, cls) + copy_reg.pickle(cls, lambda obj: (cls, (), obj.__getstate__())) + + +def _AddDescriptors(message_descriptor, dictionary): + """Sets up a new protocol message class dictionary. + + Args: + message_descriptor: A Descriptor instance describing this message type. + dictionary: Class dictionary to which we'll add a '__slots__' entry. + """ + dictionary['__descriptors'] = {} + for field in message_descriptor.fields: + dictionary['__descriptors'][field.name] = GetFieldDescriptor( + field.full_name) + + dictionary['__slots__'] = list(dictionary['__descriptors'].iterkeys()) + [ + '_cmsg', '_owner', '_composite_fields', 'Extensions', '_HACK_REFCOUNTS'] + + +def _AddEnumValues(message_descriptor, dictionary): + """Sets class-level attributes for all enum fields defined in this message. + + Args: + message_descriptor: Descriptor object for this message type. + dictionary: Class dictionary that should be populated. + """ + for enum_type in message_descriptor.enum_types: + dictionary[enum_type.name] = enum_type_wrapper.EnumTypeWrapper(enum_type) + for enum_value in enum_type.values: + dictionary[enum_value.name] = enum_value.number + + +def _AddClassAttributesForNestedExtensions(message_descriptor, dictionary): + """Adds class attributes for the nested extensions.""" + extension_dict = message_descriptor.extensions_by_name + for extension_name, extension_field in extension_dict.iteritems(): + assert extension_name not in dictionary + dictionary[extension_name] = extension_field + + +def _AddInitMethod(message_descriptor, cls): + """Adds an __init__ method to cls.""" + + # Create and attach message field properties to the message class. + # This can be done just once per message class, since property setters and + # getters are passed the message instance. + # This makes message instantiation extremely fast, and at the same time it + # doesn't require the creation of property objects for each message instance, + # which saves a lot of memory. + for field in message_descriptor.fields: + field_cdescriptor = cls.__descriptors[field.name] + if field.label == _LABEL_REPEATED: + if field.cpp_type == _CPPTYPE_MESSAGE: + value = RepeatedCompositeProperty(field_cdescriptor, field.message_type) + else: + value = RepeatedScalarProperty(field_cdescriptor) + elif field.cpp_type == _CPPTYPE_MESSAGE: + value = CompositeProperty(field_cdescriptor, field.message_type) + else: + value = ScalarProperty(field_cdescriptor) + setattr(cls, field.name, value) + + # Attach a constant with the field number. + constant_name = field.name.upper() + '_FIELD_NUMBER' + setattr(cls, constant_name, field.number) + + def Init(self, **kwargs): + """Message constructor.""" + cmessage = kwargs.pop('__cmessage', None) + if cmessage: + self._cmsg = cmessage + else: + self._cmsg = NewCMessage(message_descriptor.full_name) + + # Keep a reference to the owner, as the owner keeps a reference to the + # underlying protocol buffer message. + owner = kwargs.pop('__owner', None) + if owner: + self._owner = owner + + if message_descriptor.is_extendable: + self.Extensions = ExtensionDict(self) + else: + # Reference counting in the C++ code is broken and depends on + # the Extensions reference to keep this object alive during unit + # tests (see b/4856052). Remove this once b/4945904 is fixed. + self._HACK_REFCOUNTS = self + self._composite_fields = {} + + for field_name, field_value in kwargs.iteritems(): + field_cdescriptor = self.__descriptors.get(field_name, None) + if not field_cdescriptor: + raise ValueError('Protocol message has no "%s" field.' % field_name) + if field_cdescriptor.label == _LABEL_REPEATED: + if field_cdescriptor.cpp_type == _CPPTYPE_MESSAGE: + field_name = getattr(self, field_name) + for val in field_value: + field_name.add().MergeFrom(val) + else: + getattr(self, field_name).extend(field_value) + elif field_cdescriptor.cpp_type == _CPPTYPE_MESSAGE: + getattr(self, field_name).MergeFrom(field_value) + else: + setattr(self, field_name, field_value) + + Init.__module__ = None + Init.__doc__ = None + cls.__init__ = Init + + +def _IsMessageSetExtension(field): + """Checks if a field is a message set extension.""" + return (field.is_extension and + field.containing_type.has_options and + field.containing_type.GetOptions().message_set_wire_format and + field.type == _TYPE_MESSAGE and + field.message_type == field.extension_scope and + field.label == _LABEL_OPTIONAL) + + +def _AddMessageMethods(message_descriptor, cls): + """Adds the methods to a protocol message class.""" + if message_descriptor.is_extendable: + + def ClearExtension(self, extension): + self.Extensions.ClearExtension(extension) + + def HasExtension(self, extension): + return self.Extensions.HasExtension(extension) + + def HasField(self, field_name): + return self._cmsg.HasField(field_name) + + def ClearField(self, field_name): + child_cmessage = None + if field_name in self._composite_fields: + child_field = self._composite_fields[field_name] + del self._composite_fields[field_name] + + child_cdescriptor = self.__descriptors[field_name] + # TODO(anuraag): Support clearing repeated message fields as well. + if (child_cdescriptor.label != _LABEL_REPEATED and + child_cdescriptor.cpp_type == _CPPTYPE_MESSAGE): + child_field._owner = None + child_cmessage = child_field._cmsg + + if child_cmessage is not None: + self._cmsg.ClearField(field_name, child_cmessage) + else: + self._cmsg.ClearField(field_name) + + def Clear(self): + cmessages_to_release = [] + for field_name, child_field in self._composite_fields.iteritems(): + child_cdescriptor = self.__descriptors[field_name] + # TODO(anuraag): Support clearing repeated message fields as well. + if (child_cdescriptor.label != _LABEL_REPEATED and + child_cdescriptor.cpp_type == _CPPTYPE_MESSAGE): + child_field._owner = None + cmessages_to_release.append((child_cdescriptor, child_field._cmsg)) + self._composite_fields.clear() + self._cmsg.Clear(cmessages_to_release) + + def IsInitialized(self, errors=None): + if self._cmsg.IsInitialized(): + return True + if errors is not None: + errors.extend(self.FindInitializationErrors()); + return False + + def SerializeToString(self): + if not self.IsInitialized(): + raise message.EncodeError( + 'Message %s is missing required fields: %s' % ( + self._cmsg.full_name, ','.join(self.FindInitializationErrors()))) + return self._cmsg.SerializeToString() + + def SerializePartialToString(self): + return self._cmsg.SerializePartialToString() + + def ParseFromString(self, serialized): + self.Clear() + self.MergeFromString(serialized) + + def MergeFromString(self, serialized): + byte_size = self._cmsg.MergeFromString(serialized) + if byte_size < 0: + raise message.DecodeError('Unable to merge from string.') + return byte_size + + def MergeFrom(self, msg): + if not isinstance(msg, cls): + raise TypeError( + "Parameter to MergeFrom() must be instance of same class: " + "expected %s got %s." % (cls.__name__, type(msg).__name__)) + self._cmsg.MergeFrom(msg._cmsg) + + def CopyFrom(self, msg): + self._cmsg.CopyFrom(msg._cmsg) + + def ByteSize(self): + return self._cmsg.ByteSize() + + def SetInParent(self): + return self._cmsg.SetInParent() + + def ListFields(self): + all_fields = [] + field_list = self._cmsg.ListFields() + fields_by_name = cls.DESCRIPTOR.fields_by_name + for is_extension, field_name in field_list: + if is_extension: + extension = cls._extensions_by_name[field_name] + all_fields.append((extension, self.Extensions[extension])) + else: + field_descriptor = fields_by_name[field_name] + all_fields.append( + (field_descriptor, getattr(self, field_name))) + all_fields.sort(key=lambda item: item[0].number) + return all_fields + + def FindInitializationErrors(self): + return self._cmsg.FindInitializationErrors() + + def __str__(self): + return str(self._cmsg) + + def __eq__(self, other): + if self is other: + return True + if not isinstance(other, self.__class__): + return False + return self.ListFields() == other.ListFields() + + def __ne__(self, other): + return not self == other + + def __hash__(self): + raise TypeError('unhashable object') + + def __unicode__(self): + # Lazy import to prevent circular import when text_format imports this file. + from google.protobuf import text_format + return text_format.MessageToString(self, as_utf8=True).decode('utf-8') + + # Attach the local methods to the message class. + for key, value in locals().copy().iteritems(): + if key not in ('key', 'value', '__builtins__', '__name__', '__doc__'): + setattr(cls, key, value) + + # Static methods: + + def RegisterExtension(extension_handle): + extension_handle.containing_type = cls.DESCRIPTOR + cls._extensions_by_name[extension_handle.full_name] = extension_handle + + if _IsMessageSetExtension(extension_handle): + # MessageSet extension. Also register under type name. + cls._extensions_by_name[ + extension_handle.message_type.full_name] = extension_handle + cls.RegisterExtension = staticmethod(RegisterExtension) + + def FromString(string): + msg = cls() + msg.MergeFromString(string) + return msg + cls.FromString = staticmethod(FromString) + + + +def _AddPropertiesForExtensions(message_descriptor, cls): + """Adds properties for all fields in this protocol message type.""" + extension_dict = message_descriptor.extensions_by_name + for extension_name, extension_field in extension_dict.iteritems(): + constant_name = extension_name.upper() + '_FIELD_NUMBER' + setattr(cls, constant_name, extension_field.number) diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py index 461a30c..651ee0d 100755 --- a/python/google/protobuf/internal/decoder.py +++ b/python/google/protobuf/internal/decoder.py @@ -28,6 +28,10 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#PY25 compatible for GAE. +# +# Copyright 2009 Google Inc. All Rights Reserved. + """Code for decoding protocol buffer primitives. This code is very similar to encoder.py -- read the docs for that module first. @@ -81,17 +85,26 @@ we repeatedly read a tag, look up the corresponding decoder, and invoke it. __author__ = 'kenton@google.com (Kenton Varda)' import struct +import sys ##PY25 +_PY2 = sys.version_info[0] < 3 ##PY25 from google.protobuf.internal import encoder from google.protobuf.internal import wire_format from google.protobuf import message +# This will overflow and thus become IEEE-754 "infinity". We would use +# "float('inf')" but it doesn't work on Windows pre-Python-2.6. +_POS_INF = 1e10000 +_NEG_INF = -_POS_INF +_NAN = _POS_INF * 0 + + # This is not for optimization, but rather to avoid conflicts with local # variables named "message". _DecodeError = message.DecodeError -def _VarintDecoder(mask): +def _VarintDecoder(mask, result_type): """Return an encoder for a basic varint value (does not include tag). Decoded values will be bitwise-anded with the given mask before being @@ -102,15 +115,18 @@ def _VarintDecoder(mask): """ local_ord = ord + py2 = _PY2 ##PY25 +##!PY25 py2 = str is bytes def DecodeVarint(buffer, pos): result = 0 shift = 0 while 1: - b = local_ord(buffer[pos]) + b = local_ord(buffer[pos]) if py2 else buffer[pos] result |= ((b & 0x7f) << shift) pos += 1 if not (b & 0x80): result &= mask + result = result_type(result) return (result, pos) shift += 7 if shift >= 64: @@ -118,15 +134,17 @@ def _VarintDecoder(mask): return DecodeVarint -def _SignedVarintDecoder(mask): +def _SignedVarintDecoder(mask, result_type): """Like _VarintDecoder() but decodes signed values.""" local_ord = ord + py2 = _PY2 ##PY25 +##!PY25 py2 = str is bytes def DecodeVarint(buffer, pos): result = 0 shift = 0 while 1: - b = local_ord(buffer[pos]) + b = local_ord(buffer[pos]) if py2 else buffer[pos] result |= ((b & 0x7f) << shift) pos += 1 if not (b & 0x80): @@ -135,19 +153,23 @@ def _SignedVarintDecoder(mask): result |= ~mask else: result &= mask + result = result_type(result) return (result, pos) shift += 7 if shift >= 64: raise _DecodeError('Too many bytes when decoding varint.') return DecodeVarint +# We force 32-bit values to int and 64-bit values to long to make +# alternate implementations where the distinction is more significant +# (e.g. the C++ implementation) simpler. -_DecodeVarint = _VarintDecoder((1 << 64) - 1) -_DecodeSignedVarint = _SignedVarintDecoder((1 << 64) - 1) +_DecodeVarint = _VarintDecoder((1 << 64) - 1, long) +_DecodeSignedVarint = _SignedVarintDecoder((1 << 64) - 1, long) # Use these versions for values which must be limited to 32 bits. -_DecodeVarint32 = _VarintDecoder((1 << 32) - 1) -_DecodeSignedVarint32 = _SignedVarintDecoder((1 << 32) - 1) +_DecodeVarint32 = _VarintDecoder((1 << 32) - 1, int) +_DecodeSignedVarint32 = _SignedVarintDecoder((1 << 32) - 1, int) def ReadTag(buffer, pos): @@ -161,8 +183,10 @@ def ReadTag(buffer, pos): use that, but not in Python. """ + py2 = _PY2 ##PY25 +##!PY25 py2 = str is bytes start = pos - while ord(buffer[pos]) & 0x80: + while (ord(buffer[pos]) if py2 else buffer[pos]) & 0x80: pos += 1 pos += 1 return (buffer[start:pos], pos) @@ -269,10 +293,161 @@ def _StructPackDecoder(wire_type, format): return _SimpleDecoder(wire_type, InnerDecode) +def _FloatDecoder(): + """Returns a decoder for a float field. + + This code works around a bug in struct.unpack for non-finite 32-bit + floating-point values. + """ + + local_unpack = struct.unpack + b = (lambda x:x) if _PY2 else lambda x:x.encode('latin1') ##PY25 + + def InnerDecode(buffer, pos): + # We expect a 32-bit value in little-endian byte order. Bit 1 is the sign + # bit, bits 2-9 represent the exponent, and bits 10-32 are the significand. + new_pos = pos + 4 + float_bytes = buffer[pos:new_pos] + + # If this value has all its exponent bits set, then it's non-finite. + # In Python 2.4, struct.unpack will convert it to a finite 64-bit value. + # To avoid that, we parse it specially. + if ((float_bytes[3:4] in b('\x7F\xFF')) ##PY25 +##!PY25 if ((float_bytes[3:4] in b'\x7F\xFF') + and (float_bytes[2:3] >= b('\x80'))): ##PY25 +##!PY25 and (float_bytes[2:3] >= b'\x80')): + # If at least one significand bit is set... + if float_bytes[0:3] != b('\x00\x00\x80'): ##PY25 +##!PY25 if float_bytes[0:3] != b'\x00\x00\x80': + return (_NAN, new_pos) + # If sign bit is set... + if float_bytes[3:4] == b('\xFF'): ##PY25 +##!PY25 if float_bytes[3:4] == b'\xFF': + return (_NEG_INF, new_pos) + return (_POS_INF, new_pos) + + # Note that we expect someone up-stack to catch struct.error and convert + # it to _DecodeError -- this way we don't have to set up exception- + # handling blocks every time we parse one value. + result = local_unpack('= b'\xF0') +##!PY25 and (double_bytes[0:7] != b'\x00\x00\x00\x00\x00\x00\xF0')): + if ((double_bytes[7:8] in b('\x7F\xFF')) ##PY25 + and (double_bytes[6:7] >= b('\xF0')) ##PY25 + and (double_bytes[0:7] != b('\x00\x00\x00\x00\x00\x00\xF0'))): ##PY25 + return (_NAN, new_pos) + + # Note that we expect someone up-stack to catch struct.error and convert + # it to _DecodeError -- this way we don't have to set up exception- + # handling blocks every time we parse one value. + result = local_unpack(' end: + raise _DecodeError('Truncated message.') + while pos < endpoint: + value_start_pos = pos + (element, pos) = _DecodeSignedVarint32(buffer, pos) + if element in enum_type.values_by_number: + value.append(element) + else: + if not message._unknown_fields: + message._unknown_fields = [] + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_VARINT) + message._unknown_fields.append( + (tag_bytes, buffer[value_start_pos:pos])) + if pos > endpoint: + if element in enum_type.values_by_number: + del value[-1] # Discard corrupt value. + else: + del message._unknown_fields[-1] + raise _DecodeError('Packed element was truncated.') + return pos + return DecodePackedField + elif is_repeated: + tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_VARINT) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + (element, new_pos) = _DecodeSignedVarint32(buffer, pos) + if element in enum_type.values_by_number: + value.append(element) + else: + if not message._unknown_fields: + message._unknown_fields = [] + message._unknown_fields.append( + (tag_bytes, buffer[pos:new_pos])) + # Predict that the next tag is another copy of the same repeated + # field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos >= end: + # Prediction failed. Return. + if new_pos > end: + raise _DecodeError('Truncated message.') + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + value_start_pos = pos + (enum_value, pos) = _DecodeSignedVarint32(buffer, pos) + if pos > end: + raise _DecodeError('Truncated message.') + if enum_value in enum_type.values_by_number: + field_dict[key] = enum_value + else: + if not message._unknown_fields: + message._unknown_fields = [] + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_VARINT) + message._unknown_fields.append( + (tag_bytes, buffer[value_start_pos:pos])) + return pos + return DecodeField + + # -------------------------------------------------------------------- -Int32Decoder = EnumDecoder = _SimpleDecoder( +Int32Decoder = _SimpleDecoder( wire_format.WIRETYPE_VARINT, _DecodeSignedVarint32) Int64Decoder = _SimpleDecoder( @@ -294,8 +469,8 @@ Fixed32Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, ' end: raise _DecodeError('Truncated string.') - value.append(local_unicode(buffer[pos:new_pos], 'utf-8')) + value.append(_ConvertToUnicode(buffer[pos:new_pos])) # Predict that the next tag is another copy of the same repeated field. pos = new_pos + tag_len if buffer[new_pos:pos] != tag_bytes or new_pos == end: @@ -334,7 +517,7 @@ def StringDecoder(field_number, is_repeated, is_packed, key, new_default): new_pos = pos + size if new_pos > end: raise _DecodeError('Truncated string.') - field_dict[key] = local_unicode(buffer[pos:new_pos], 'utf-8') + field_dict[key] = _ConvertToUnicode(buffer[pos:new_pos]) return new_pos return DecodeField @@ -503,6 +686,7 @@ def MessageSetItemDecoder(extensions_by_number): local_SkipField = SkipField def DecodeItem(buffer, pos, end, message, field_dict): + message_set_item_start = pos type_id = -1 message_start = -1 message_end = -1 @@ -541,6 +725,11 @@ def MessageSetItemDecoder(extensions_by_number): # The only reason _InternalParse would return early is if it encountered # an end-group tag. raise _DecodeError('Unexpected end-group tag.') + else: + if not message._unknown_fields: + message._unknown_fields = [] + message._unknown_fields.append((MESSAGE_SET_ITEM_TAG, + buffer[message_set_item_start:pos])) return pos @@ -552,8 +741,10 @@ def MessageSetItemDecoder(extensions_by_number): def _SkipVarint(buffer, pos, end): """Skip a varint value. Returns the new position.""" - - while ord(buffer[pos]) & 0x80: + # Previously ord(buffer[pos]) raised IndexError when pos is out of range. + # With this code, ord(b'') raises TypeError. Both are handled in + # python_message.py to generate a 'Truncated message' error. + while ord(buffer[pos:pos+1]) & 0x80: pos += 1 pos += 1 if pos > end: @@ -620,7 +811,6 @@ def _FieldSkipper(): ] wiretype_mask = wire_format.TAG_TYPE_MASK - local_ord = ord def SkipField(buffer, pos, end, tag_bytes): """Skips a field with the specified tag. @@ -633,7 +823,7 @@ def _FieldSkipper(): """ # The wire type is always in the first byte since varints are little-endian. - wire_type = local_ord(tag_bytes[0]) & wiretype_mask + wire_type = ord(tag_bytes[0:1]) & wiretype_mask return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, end) return SkipField diff --git a/python/google/protobuf/internal/descriptor_database_test.py b/python/google/protobuf/internal/descriptor_database_test.py new file mode 100644 index 0000000..856f472 --- /dev/null +++ b/python/google/protobuf/internal/descriptor_database_test.py @@ -0,0 +1,63 @@ +#! /usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Tests for google.protobuf.descriptor_database.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +from google.apputils import basetest +from google.protobuf import descriptor_pb2 +from google.protobuf.internal import factory_test2_pb2 +from google.protobuf import descriptor_database + + +class DescriptorDatabaseTest(basetest.TestCase): + + def testAdd(self): + db = descriptor_database.DescriptorDatabase() + file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString( + factory_test2_pb2.DESCRIPTOR.serialized_pb) + db.Add(file_desc_proto) + + self.assertEquals(file_desc_proto, db.FindFileByName( + 'google/protobuf/internal/factory_test2.proto')) + self.assertEquals(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message')) + self.assertEquals(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.NestedFactory2Message')) + self.assertEquals(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Enum')) + self.assertEquals(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.NestedFactory2Enum')) + +if __name__ == '__main__': + basetest.main() diff --git a/python/google/protobuf/internal/descriptor_pool_test.py b/python/google/protobuf/internal/descriptor_pool_test.py new file mode 100644 index 0000000..7c1ce2e --- /dev/null +++ b/python/google/protobuf/internal/descriptor_pool_test.py @@ -0,0 +1,564 @@ +#! /usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Tests for google.protobuf.descriptor_pool.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +import os +import unittest + +from google.apputils import basetest +from google.protobuf import unittest_pb2 +from google.protobuf import descriptor_pb2 +from google.protobuf.internal import api_implementation +from google.protobuf.internal import descriptor_pool_test1_pb2 +from google.protobuf.internal import descriptor_pool_test2_pb2 +from google.protobuf.internal import factory_test1_pb2 +from google.protobuf.internal import factory_test2_pb2 +from google.protobuf import descriptor +from google.protobuf import descriptor_database +from google.protobuf import descriptor_pool + + +class DescriptorPoolTest(basetest.TestCase): + + def setUp(self): + self.pool = descriptor_pool.DescriptorPool() + self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test1_pb2.DESCRIPTOR.serialized_pb) + self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test2_pb2.DESCRIPTOR.serialized_pb) + self.pool.Add(self.factory_test1_fd) + self.pool.Add(self.factory_test2_fd) + + def testFindFileByName(self): + name1 = 'google/protobuf/internal/factory_test1.proto' + file_desc1 = self.pool.FindFileByName(name1) + self.assertIsInstance(file_desc1, descriptor.FileDescriptor) + self.assertEquals(name1, file_desc1.name) + self.assertEquals('google.protobuf.python.internal', file_desc1.package) + self.assertIn('Factory1Message', file_desc1.message_types_by_name) + + name2 = 'google/protobuf/internal/factory_test2.proto' + file_desc2 = self.pool.FindFileByName(name2) + self.assertIsInstance(file_desc2, descriptor.FileDescriptor) + self.assertEquals(name2, file_desc2.name) + self.assertEquals('google.protobuf.python.internal', file_desc2.package) + self.assertIn('Factory2Message', file_desc2.message_types_by_name) + + def testFindFileByNameFailure(self): + with self.assertRaises(KeyError): + self.pool.FindFileByName('Does not exist') + + def testFindFileContainingSymbol(self): + file_desc1 = self.pool.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory1Message') + self.assertIsInstance(file_desc1, descriptor.FileDescriptor) + self.assertEquals('google/protobuf/internal/factory_test1.proto', + file_desc1.name) + self.assertEquals('google.protobuf.python.internal', file_desc1.package) + self.assertIn('Factory1Message', file_desc1.message_types_by_name) + + file_desc2 = self.pool.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message') + self.assertIsInstance(file_desc2, descriptor.FileDescriptor) + self.assertEquals('google/protobuf/internal/factory_test2.proto', + file_desc2.name) + self.assertEquals('google.protobuf.python.internal', file_desc2.package) + self.assertIn('Factory2Message', file_desc2.message_types_by_name) + + def testFindFileContainingSymbolFailure(self): + with self.assertRaises(KeyError): + self.pool.FindFileContainingSymbol('Does not exist') + + def testFindMessageTypeByName(self): + msg1 = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory1Message') + self.assertIsInstance(msg1, descriptor.Descriptor) + self.assertEquals('Factory1Message', msg1.name) + self.assertEquals('google.protobuf.python.internal.Factory1Message', + msg1.full_name) + self.assertEquals(None, msg1.containing_type) + + nested_msg1 = msg1.nested_types[0] + self.assertEquals('NestedFactory1Message', nested_msg1.name) + self.assertEquals(msg1, nested_msg1.containing_type) + + nested_enum1 = msg1.enum_types[0] + self.assertEquals('NestedFactory1Enum', nested_enum1.name) + self.assertEquals(msg1, nested_enum1.containing_type) + + self.assertEquals(nested_msg1, msg1.fields_by_name[ + 'nested_factory_1_message'].message_type) + self.assertEquals(nested_enum1, msg1.fields_by_name[ + 'nested_factory_1_enum'].enum_type) + + msg2 = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message') + self.assertIsInstance(msg2, descriptor.Descriptor) + self.assertEquals('Factory2Message', msg2.name) + self.assertEquals('google.protobuf.python.internal.Factory2Message', + msg2.full_name) + self.assertIsNone(msg2.containing_type) + + nested_msg2 = msg2.nested_types[0] + self.assertEquals('NestedFactory2Message', nested_msg2.name) + self.assertEquals(msg2, nested_msg2.containing_type) + + nested_enum2 = msg2.enum_types[0] + self.assertEquals('NestedFactory2Enum', nested_enum2.name) + self.assertEquals(msg2, nested_enum2.containing_type) + + self.assertEquals(nested_msg2, msg2.fields_by_name[ + 'nested_factory_2_message'].message_type) + self.assertEquals(nested_enum2, msg2.fields_by_name[ + 'nested_factory_2_enum'].enum_type) + + self.assertTrue(msg2.fields_by_name['int_with_default'].has_default_value) + self.assertEquals( + 1776, msg2.fields_by_name['int_with_default'].default_value) + + self.assertTrue( + msg2.fields_by_name['double_with_default'].has_default_value) + self.assertEquals( + 9.99, msg2.fields_by_name['double_with_default'].default_value) + + self.assertTrue( + msg2.fields_by_name['string_with_default'].has_default_value) + self.assertEquals( + 'hello world', msg2.fields_by_name['string_with_default'].default_value) + + self.assertTrue(msg2.fields_by_name['bool_with_default'].has_default_value) + self.assertFalse(msg2.fields_by_name['bool_with_default'].default_value) + + self.assertTrue(msg2.fields_by_name['enum_with_default'].has_default_value) + self.assertEquals( + 1, msg2.fields_by_name['enum_with_default'].default_value) + + msg3 = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message.NestedFactory2Message') + self.assertEquals(nested_msg2, msg3) + + self.assertTrue(msg2.fields_by_name['bytes_with_default'].has_default_value) + self.assertEquals( + b'a\xfb\x00c', + msg2.fields_by_name['bytes_with_default'].default_value) + + self.assertEqual(1, len(msg2.oneofs)) + self.assertEqual(1, len(msg2.oneofs_by_name)) + self.assertEqual(2, len(msg2.oneofs[0].fields)) + for name in ['oneof_int', 'oneof_string']: + self.assertEqual(msg2.oneofs[0], + msg2.fields_by_name[name].containing_oneof) + self.assertIn(msg2.fields_by_name[name], msg2.oneofs[0].fields) + + def testFindMessageTypeByNameFailure(self): + with self.assertRaises(KeyError): + self.pool.FindMessageTypeByName('Does not exist') + + def testFindEnumTypeByName(self): + enum1 = self.pool.FindEnumTypeByName( + 'google.protobuf.python.internal.Factory1Enum') + self.assertIsInstance(enum1, descriptor.EnumDescriptor) + self.assertEquals(0, enum1.values_by_name['FACTORY_1_VALUE_0'].number) + self.assertEquals(1, enum1.values_by_name['FACTORY_1_VALUE_1'].number) + + nested_enum1 = self.pool.FindEnumTypeByName( + 'google.protobuf.python.internal.Factory1Message.NestedFactory1Enum') + self.assertIsInstance(nested_enum1, descriptor.EnumDescriptor) + self.assertEquals( + 0, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_0'].number) + self.assertEquals( + 1, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_1'].number) + + enum2 = self.pool.FindEnumTypeByName( + 'google.protobuf.python.internal.Factory2Enum') + self.assertIsInstance(enum2, descriptor.EnumDescriptor) + self.assertEquals(0, enum2.values_by_name['FACTORY_2_VALUE_0'].number) + self.assertEquals(1, enum2.values_by_name['FACTORY_2_VALUE_1'].number) + + nested_enum2 = self.pool.FindEnumTypeByName( + 'google.protobuf.python.internal.Factory2Message.NestedFactory2Enum') + self.assertIsInstance(nested_enum2, descriptor.EnumDescriptor) + self.assertEquals( + 0, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_0'].number) + self.assertEquals( + 1, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_1'].number) + + def testFindEnumTypeByNameFailure(self): + with self.assertRaises(KeyError): + self.pool.FindEnumTypeByName('Does not exist') + + def testUserDefinedDB(self): + db = descriptor_database.DescriptorDatabase() + self.pool = descriptor_pool.DescriptorPool(db) + db.Add(self.factory_test1_fd) + db.Add(self.factory_test2_fd) + self.testFindMessageTypeByName() + + def testComplexNesting(self): + test1_desc = descriptor_pb2.FileDescriptorProto.FromString( + descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb) + test2_desc = descriptor_pb2.FileDescriptorProto.FromString( + descriptor_pool_test2_pb2.DESCRIPTOR.serialized_pb) + self.pool.Add(test1_desc) + self.pool.Add(test2_desc) + TEST1_FILE.CheckFile(self, self.pool) + TEST2_FILE.CheckFile(self, self.pool) + + + +class ProtoFile(object): + + def __init__(self, name, package, messages, dependencies=None): + self.name = name + self.package = package + self.messages = messages + self.dependencies = dependencies or [] + + def CheckFile(self, test, pool): + file_desc = pool.FindFileByName(self.name) + test.assertEquals(self.name, file_desc.name) + test.assertEquals(self.package, file_desc.package) + dependencies_names = [f.name for f in file_desc.dependencies] + test.assertEqual(self.dependencies, dependencies_names) + for name, msg_type in self.messages.items(): + msg_type.CheckType(test, None, name, file_desc) + + +class EnumType(object): + + def __init__(self, values): + self.values = values + + def CheckType(self, test, msg_desc, name, file_desc): + enum_desc = msg_desc.enum_types_by_name[name] + test.assertEqual(name, enum_desc.name) + expected_enum_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_enum_full_name, enum_desc.full_name) + test.assertEqual(msg_desc, enum_desc.containing_type) + test.assertEqual(file_desc, enum_desc.file) + for index, (value, number) in enumerate(self.values): + value_desc = enum_desc.values_by_name[value] + test.assertEqual(value, value_desc.name) + test.assertEqual(index, value_desc.index) + test.assertEqual(number, value_desc.number) + test.assertEqual(enum_desc, value_desc.type) + test.assertIn(value, msg_desc.enum_values_by_name) + + +class MessageType(object): + + def __init__(self, type_dict, field_list, is_extendable=False, + extensions=None): + self.type_dict = type_dict + self.field_list = field_list + self.is_extendable = is_extendable + self.extensions = extensions or [] + + def CheckType(self, test, containing_type_desc, name, file_desc): + if containing_type_desc is None: + desc = file_desc.message_types_by_name[name] + expected_full_name = '.'.join([file_desc.package, name]) + else: + desc = containing_type_desc.nested_types_by_name[name] + expected_full_name = '.'.join([containing_type_desc.full_name, name]) + + test.assertEqual(name, desc.name) + test.assertEqual(expected_full_name, desc.full_name) + test.assertEqual(containing_type_desc, desc.containing_type) + test.assertEqual(desc.file, file_desc) + test.assertEqual(self.is_extendable, desc.is_extendable) + for name, subtype in self.type_dict.items(): + subtype.CheckType(test, desc, name, file_desc) + + for index, (name, field) in enumerate(self.field_list): + field.CheckField(test, desc, name, index) + + for index, (name, field) in enumerate(self.extensions): + field.CheckField(test, desc, name, index) + + +class EnumField(object): + + def __init__(self, number, type_name, default_value): + self.number = number + self.type_name = type_name + self.default_value = default_value + + def CheckField(self, test, msg_desc, name, index): + field_desc = msg_desc.fields_by_name[name] + enum_desc = msg_desc.enum_types_by_name[self.type_name] + test.assertEqual(name, field_desc.name) + expected_field_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_field_full_name, field_desc.full_name) + test.assertEqual(index, field_desc.index) + test.assertEqual(self.number, field_desc.number) + test.assertEqual(descriptor.FieldDescriptor.TYPE_ENUM, field_desc.type) + test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_ENUM, + field_desc.cpp_type) + test.assertTrue(field_desc.has_default_value) + test.assertEqual(enum_desc.values_by_name[self.default_value].index, + field_desc.default_value) + test.assertEqual(msg_desc, field_desc.containing_type) + test.assertEqual(enum_desc, field_desc.enum_type) + + +class MessageField(object): + + def __init__(self, number, type_name): + self.number = number + self.type_name = type_name + + def CheckField(self, test, msg_desc, name, index): + field_desc = msg_desc.fields_by_name[name] + field_type_desc = msg_desc.nested_types_by_name[self.type_name] + test.assertEqual(name, field_desc.name) + expected_field_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_field_full_name, field_desc.full_name) + test.assertEqual(index, field_desc.index) + test.assertEqual(self.number, field_desc.number) + test.assertEqual(descriptor.FieldDescriptor.TYPE_MESSAGE, field_desc.type) + test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_MESSAGE, + field_desc.cpp_type) + test.assertFalse(field_desc.has_default_value) + test.assertEqual(msg_desc, field_desc.containing_type) + test.assertEqual(field_type_desc, field_desc.message_type) + + +class StringField(object): + + def __init__(self, number, default_value): + self.number = number + self.default_value = default_value + + def CheckField(self, test, msg_desc, name, index): + field_desc = msg_desc.fields_by_name[name] + test.assertEqual(name, field_desc.name) + expected_field_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_field_full_name, field_desc.full_name) + test.assertEqual(index, field_desc.index) + test.assertEqual(self.number, field_desc.number) + test.assertEqual(descriptor.FieldDescriptor.TYPE_STRING, field_desc.type) + test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_STRING, + field_desc.cpp_type) + test.assertTrue(field_desc.has_default_value) + test.assertEqual(self.default_value, field_desc.default_value) + + +class ExtensionField(object): + + def __init__(self, number, extended_type): + self.number = number + self.extended_type = extended_type + + def CheckField(self, test, msg_desc, name, index): + field_desc = msg_desc.extensions_by_name[name] + test.assertEqual(name, field_desc.name) + expected_field_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_field_full_name, field_desc.full_name) + test.assertEqual(self.number, field_desc.number) + test.assertEqual(index, field_desc.index) + test.assertEqual(descriptor.FieldDescriptor.TYPE_MESSAGE, field_desc.type) + test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_MESSAGE, + field_desc.cpp_type) + test.assertFalse(field_desc.has_default_value) + test.assertTrue(field_desc.is_extension) + test.assertEqual(msg_desc, field_desc.extension_scope) + test.assertEqual(msg_desc, field_desc.message_type) + test.assertEqual(self.extended_type, field_desc.containing_type.name) + + +class AddDescriptorTest(basetest.TestCase): + + def _TestMessage(self, prefix): + pool = descriptor_pool.DescriptorPool() + pool.AddDescriptor(unittest_pb2.TestAllTypes.DESCRIPTOR) + self.assertEquals( + 'protobuf_unittest.TestAllTypes', + pool.FindMessageTypeByName( + prefix + 'protobuf_unittest.TestAllTypes').full_name) + + # AddDescriptor is not recursive. + with self.assertRaises(KeyError): + pool.FindMessageTypeByName( + prefix + 'protobuf_unittest.TestAllTypes.NestedMessage') + + pool.AddDescriptor(unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR) + self.assertEquals( + 'protobuf_unittest.TestAllTypes.NestedMessage', + pool.FindMessageTypeByName( + prefix + 'protobuf_unittest.TestAllTypes.NestedMessage').full_name) + + # Files are implicitly also indexed when messages are added. + self.assertEquals( + 'google/protobuf/unittest.proto', + pool.FindFileByName( + 'google/protobuf/unittest.proto').name) + + self.assertEquals( + 'google/protobuf/unittest.proto', + pool.FindFileContainingSymbol( + prefix + 'protobuf_unittest.TestAllTypes.NestedMessage').name) + + def testMessage(self): + self._TestMessage('') + self._TestMessage('.') + + def _TestEnum(self, prefix): + pool = descriptor_pool.DescriptorPool() + pool.AddEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR) + self.assertEquals( + 'protobuf_unittest.ForeignEnum', + pool.FindEnumTypeByName( + prefix + 'protobuf_unittest.ForeignEnum').full_name) + + # AddEnumDescriptor is not recursive. + with self.assertRaises(KeyError): + pool.FindEnumTypeByName( + prefix + 'protobuf_unittest.ForeignEnum.NestedEnum') + + pool.AddEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR) + self.assertEquals( + 'protobuf_unittest.TestAllTypes.NestedEnum', + pool.FindEnumTypeByName( + prefix + 'protobuf_unittest.TestAllTypes.NestedEnum').full_name) + + # Files are implicitly also indexed when enums are added. + self.assertEquals( + 'google/protobuf/unittest.proto', + pool.FindFileByName( + 'google/protobuf/unittest.proto').name) + + self.assertEquals( + 'google/protobuf/unittest.proto', + pool.FindFileContainingSymbol( + prefix + 'protobuf_unittest.TestAllTypes.NestedEnum').name) + + def testEnum(self): + self._TestEnum('') + self._TestEnum('.') + + def testFile(self): + pool = descriptor_pool.DescriptorPool() + pool.AddFileDescriptor(unittest_pb2.DESCRIPTOR) + self.assertEquals( + 'google/protobuf/unittest.proto', + pool.FindFileByName( + 'google/protobuf/unittest.proto').name) + + # AddFileDescriptor is not recursive; messages and enums within files must + # be explicitly registered. + with self.assertRaises(KeyError): + pool.FindFileContainingSymbol( + 'protobuf_unittest.TestAllTypes') + + +TEST1_FILE = ProtoFile( + 'google/protobuf/internal/descriptor_pool_test1.proto', + 'google.protobuf.python.internal', + { + 'DescriptorPoolTest1': MessageType({ + 'NestedEnum': EnumType([('ALPHA', 1), ('BETA', 2)]), + 'NestedMessage': MessageType({ + 'NestedEnum': EnumType([('EPSILON', 5), ('ZETA', 6)]), + 'DeepNestedMessage': MessageType({ + 'NestedEnum': EnumType([('ETA', 7), ('THETA', 8)]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'ETA')), + ('nested_field', StringField(2, 'theta')), + ]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'ZETA')), + ('nested_field', StringField(2, 'beta')), + ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), + ]) + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'BETA')), + ('nested_message', MessageField(2, 'NestedMessage')), + ], is_extendable=True), + + 'DescriptorPoolTest2': MessageType({ + 'NestedEnum': EnumType([('GAMMA', 3), ('DELTA', 4)]), + 'NestedMessage': MessageType({ + 'NestedEnum': EnumType([('IOTA', 9), ('KAPPA', 10)]), + 'DeepNestedMessage': MessageType({ + 'NestedEnum': EnumType([('LAMBDA', 11), ('MU', 12)]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'MU')), + ('nested_field', StringField(2, 'lambda')), + ]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'IOTA')), + ('nested_field', StringField(2, 'delta')), + ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), + ]) + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'GAMMA')), + ('nested_message', MessageField(2, 'NestedMessage')), + ]), + }) + + +TEST2_FILE = ProtoFile( + 'google/protobuf/internal/descriptor_pool_test2.proto', + 'google.protobuf.python.internal', + { + 'DescriptorPoolTest3': MessageType({ + 'NestedEnum': EnumType([('NU', 13), ('XI', 14)]), + 'NestedMessage': MessageType({ + 'NestedEnum': EnumType([('OMICRON', 15), ('PI', 16)]), + 'DeepNestedMessage': MessageType({ + 'NestedEnum': EnumType([('RHO', 17), ('SIGMA', 18)]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'RHO')), + ('nested_field', StringField(2, 'sigma')), + ]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'PI')), + ('nested_field', StringField(2, 'nu')), + ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), + ]) + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'XI')), + ('nested_message', MessageField(2, 'NestedMessage')), + ], extensions=[ + ('descriptor_pool_test', + ExtensionField(1001, 'DescriptorPoolTest1')), + ]), + }, + dependencies=['google/protobuf/internal/descriptor_pool_test1.proto']) + + +if __name__ == '__main__': + basetest.main() diff --git a/python/google/protobuf/internal/descriptor_pool_test1.proto b/python/google/protobuf/internal/descriptor_pool_test1.proto new file mode 100644 index 0000000..c11dcc0 --- /dev/null +++ b/python/google/protobuf/internal/descriptor_pool_test1.proto @@ -0,0 +1,94 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package google.protobuf.python.internal; + + +message DescriptorPoolTest1 { + extensions 1000 to max; + + enum NestedEnum { + ALPHA = 1; + BETA = 2; + } + + optional NestedEnum nested_enum = 1 [default = BETA]; + + message NestedMessage { + enum NestedEnum { + EPSILON = 5; + ZETA = 6; + } + optional NestedEnum nested_enum = 1 [default = ZETA]; + optional string nested_field = 2 [default = "beta"]; + optional DeepNestedMessage deep_nested_message = 3; + + message DeepNestedMessage { + enum NestedEnum { + ETA = 7; + THETA = 8; + } + optional NestedEnum nested_enum = 1 [default = ETA]; + optional string nested_field = 2 [default = "theta"]; + } + } + + optional NestedMessage nested_message = 2; +} + +message DescriptorPoolTest2 { + enum NestedEnum { + GAMMA = 3; + DELTA = 4; + } + + optional NestedEnum nested_enum = 1 [default = GAMMA]; + + message NestedMessage { + enum NestedEnum { + IOTA = 9; + KAPPA = 10; + } + optional NestedEnum nested_enum = 1 [default = IOTA]; + optional string nested_field = 2 [default = "delta"]; + optional DeepNestedMessage deep_nested_message = 3; + + message DeepNestedMessage { + enum NestedEnum { + LAMBDA = 11; + MU = 12; + } + optional NestedEnum nested_enum = 1 [default = MU]; + optional string nested_field = 2 [default = "lambda"]; + } + } + + optional NestedMessage nested_message = 2; +} diff --git a/python/google/protobuf/internal/descriptor_pool_test2.proto b/python/google/protobuf/internal/descriptor_pool_test2.proto new file mode 100644 index 0000000..d97d39b --- /dev/null +++ b/python/google/protobuf/internal/descriptor_pool_test2.proto @@ -0,0 +1,70 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package google.protobuf.python.internal; + +import "google/protobuf/internal/descriptor_pool_test1.proto"; + + +message DescriptorPoolTest3 { + + extend DescriptorPoolTest1 { + optional DescriptorPoolTest3 descriptor_pool_test = 1001; + } + + enum NestedEnum { + NU = 13; + XI = 14; + } + + optional NestedEnum nested_enum = 1 [default = XI]; + + message NestedMessage { + enum NestedEnum { + OMICRON = 15; + PI = 16; + } + optional NestedEnum nested_enum = 1 [default = PI]; + optional string nested_field = 2 [default = "nu"]; + optional DeepNestedMessage deep_nested_message = 3; + + message DeepNestedMessage { + enum NestedEnum { + RHO = 17; + SIGMA = 18; + } + optional NestedEnum nested_enum = 1 [default = RHO]; + optional string nested_field = 2 [default = "sigma"]; + } + } + + optional NestedMessage nested_message = 2; +} + diff --git a/python/google/protobuf/internal/descriptor_python_test.py b/python/google/protobuf/internal/descriptor_python_test.py new file mode 100644 index 0000000..b3a1571 --- /dev/null +++ b/python/google/protobuf/internal/descriptor_python_test.py @@ -0,0 +1,54 @@ +#! /usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Unittest for descriptor.py for the pure Python implementation.""" + +import os +os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python' + +# We must set the implementation version above before the google3 imports. +# pylint: disable=g-import-not-at-top +from google.apputils import basetest +from google.protobuf.internal import api_implementation +# Run all tests from the original module by putting them in our namespace. +# pylint: disable=wildcard-import +from google.protobuf.internal.descriptor_test import * + + +class ConfirmPurePythonTest(basetest.TestCase): + + def testImplementationSetting(self): + self.assertEqual('python', api_implementation.Type()) + + +if __name__ == '__main__': + basetest.main() diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py index 05c2745..d20d945 100755 --- a/python/google/protobuf/internal/descriptor_test.py +++ b/python/google/protobuf/internal/descriptor_test.py @@ -34,7 +34,8 @@ __author__ = 'robinson@google.com (Will Robinson)' -import unittest +from google.apputils import basetest +from google.protobuf import unittest_custom_options_pb2 from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_pb2 from google.protobuf import descriptor_pb2 @@ -47,7 +48,7 @@ name: 'TestEmptyMessage' """ -class DescriptorTest(unittest.TestCase): +class DescriptorTest(basetest.TestCase): def setUp(self): self.my_file = descriptor.FileDescriptor( @@ -101,6 +102,15 @@ class DescriptorTest(unittest.TestCase): self.my_method ]) + def testEnumValueName(self): + self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4), + 'FOREIGN_FOO') + + self.assertEqual( + self.my_message.enum_types_by_name[ + 'ForeignEnum'].values_by_number[4].name, + self.my_message.EnumValueName('ForeignEnum', 4)) + def testEnumFixups(self): self.assertEqual(self.my_enum, self.my_enum.values[0].type) @@ -125,6 +135,257 @@ class DescriptorTest(unittest.TestCase): self.assertEqual(self.my_service.GetOptions(), descriptor_pb2.ServiceOptions()) + def testSimpleCustomOptions(self): + file_descriptor = unittest_custom_options_pb2.DESCRIPTOR + message_descriptor =\ + unittest_custom_options_pb2.TestMessageWithCustomOptions.DESCRIPTOR + field_descriptor = message_descriptor.fields_by_name["field1"] + enum_descriptor = message_descriptor.enum_types_by_name["AnEnum"] + enum_value_descriptor =\ + message_descriptor.enum_values_by_name["ANENUM_VAL2"] + service_descriptor =\ + unittest_custom_options_pb2.TestServiceWithCustomOptions.DESCRIPTOR + method_descriptor = service_descriptor.FindMethodByName("Foo") + + file_options = file_descriptor.GetOptions() + file_opt1 = unittest_custom_options_pb2.file_opt1 + self.assertEqual(9876543210, file_options.Extensions[file_opt1]) + message_options = message_descriptor.GetOptions() + message_opt1 = unittest_custom_options_pb2.message_opt1 + self.assertEqual(-56, message_options.Extensions[message_opt1]) + field_options = field_descriptor.GetOptions() + field_opt1 = unittest_custom_options_pb2.field_opt1 + self.assertEqual(8765432109, field_options.Extensions[field_opt1]) + field_opt2 = unittest_custom_options_pb2.field_opt2 + self.assertEqual(42, field_options.Extensions[field_opt2]) + enum_options = enum_descriptor.GetOptions() + enum_opt1 = unittest_custom_options_pb2.enum_opt1 + self.assertEqual(-789, enum_options.Extensions[enum_opt1]) + enum_value_options = enum_value_descriptor.GetOptions() + enum_value_opt1 = unittest_custom_options_pb2.enum_value_opt1 + self.assertEqual(123, enum_value_options.Extensions[enum_value_opt1]) + + service_options = service_descriptor.GetOptions() + service_opt1 = unittest_custom_options_pb2.service_opt1 + self.assertEqual(-9876543210, service_options.Extensions[service_opt1]) + method_options = method_descriptor.GetOptions() + method_opt1 = unittest_custom_options_pb2.method_opt1 + self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2, + method_options.Extensions[method_opt1]) + + def testDifferentCustomOptionTypes(self): + kint32min = -2**31 + kint64min = -2**63 + kint32max = 2**31 - 1 + kint64max = 2**63 - 1 + kuint32max = 2**32 - 1 + kuint64max = 2**64 - 1 + + message_descriptor =\ + unittest_custom_options_pb2.CustomOptionMinIntegerValues.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertEqual(False, message_options.Extensions[ + unittest_custom_options_pb2.bool_opt]) + self.assertEqual(kint32min, message_options.Extensions[ + unittest_custom_options_pb2.int32_opt]) + self.assertEqual(kint64min, message_options.Extensions[ + unittest_custom_options_pb2.int64_opt]) + self.assertEqual(0, message_options.Extensions[ + unittest_custom_options_pb2.uint32_opt]) + self.assertEqual(0, message_options.Extensions[ + unittest_custom_options_pb2.uint64_opt]) + self.assertEqual(kint32min, message_options.Extensions[ + unittest_custom_options_pb2.sint32_opt]) + self.assertEqual(kint64min, message_options.Extensions[ + unittest_custom_options_pb2.sint64_opt]) + self.assertEqual(0, message_options.Extensions[ + unittest_custom_options_pb2.fixed32_opt]) + self.assertEqual(0, message_options.Extensions[ + unittest_custom_options_pb2.fixed64_opt]) + self.assertEqual(kint32min, message_options.Extensions[ + unittest_custom_options_pb2.sfixed32_opt]) + self.assertEqual(kint64min, message_options.Extensions[ + unittest_custom_options_pb2.sfixed64_opt]) + + message_descriptor =\ + unittest_custom_options_pb2.CustomOptionMaxIntegerValues.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertEqual(True, message_options.Extensions[ + unittest_custom_options_pb2.bool_opt]) + self.assertEqual(kint32max, message_options.Extensions[ + unittest_custom_options_pb2.int32_opt]) + self.assertEqual(kint64max, message_options.Extensions[ + unittest_custom_options_pb2.int64_opt]) + self.assertEqual(kuint32max, message_options.Extensions[ + unittest_custom_options_pb2.uint32_opt]) + self.assertEqual(kuint64max, message_options.Extensions[ + unittest_custom_options_pb2.uint64_opt]) + self.assertEqual(kint32max, message_options.Extensions[ + unittest_custom_options_pb2.sint32_opt]) + self.assertEqual(kint64max, message_options.Extensions[ + unittest_custom_options_pb2.sint64_opt]) + self.assertEqual(kuint32max, message_options.Extensions[ + unittest_custom_options_pb2.fixed32_opt]) + self.assertEqual(kuint64max, message_options.Extensions[ + unittest_custom_options_pb2.fixed64_opt]) + self.assertEqual(kint32max, message_options.Extensions[ + unittest_custom_options_pb2.sfixed32_opt]) + self.assertEqual(kint64max, message_options.Extensions[ + unittest_custom_options_pb2.sfixed64_opt]) + + message_descriptor =\ + unittest_custom_options_pb2.CustomOptionOtherValues.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertEqual(-100, message_options.Extensions[ + unittest_custom_options_pb2.int32_opt]) + self.assertAlmostEqual(12.3456789, message_options.Extensions[ + unittest_custom_options_pb2.float_opt], 6) + self.assertAlmostEqual(1.234567890123456789, message_options.Extensions[ + unittest_custom_options_pb2.double_opt]) + self.assertEqual("Hello, \"World\"", message_options.Extensions[ + unittest_custom_options_pb2.string_opt]) + self.assertEqual(b"Hello\0World", message_options.Extensions[ + unittest_custom_options_pb2.bytes_opt]) + dummy_enum = unittest_custom_options_pb2.DummyMessageContainingEnum + self.assertEqual( + dummy_enum.TEST_OPTION_ENUM_TYPE2, + message_options.Extensions[unittest_custom_options_pb2.enum_opt]) + + message_descriptor =\ + unittest_custom_options_pb2.SettingRealsFromPositiveInts.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertAlmostEqual(12, message_options.Extensions[ + unittest_custom_options_pb2.float_opt], 6) + self.assertAlmostEqual(154, message_options.Extensions[ + unittest_custom_options_pb2.double_opt]) + + message_descriptor =\ + unittest_custom_options_pb2.SettingRealsFromNegativeInts.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertAlmostEqual(-12, message_options.Extensions[ + unittest_custom_options_pb2.float_opt], 6) + self.assertAlmostEqual(-154, message_options.Extensions[ + unittest_custom_options_pb2.double_opt]) + + def testComplexExtensionOptions(self): + descriptor =\ + unittest_custom_options_pb2.VariousComplexOptions.DESCRIPTOR + options = descriptor.GetOptions() + self.assertEqual(42, options.Extensions[ + unittest_custom_options_pb2.complex_opt1].foo) + self.assertEqual(324, options.Extensions[ + unittest_custom_options_pb2.complex_opt1].Extensions[ + unittest_custom_options_pb2.quux]) + self.assertEqual(876, options.Extensions[ + unittest_custom_options_pb2.complex_opt1].Extensions[ + unittest_custom_options_pb2.corge].qux) + self.assertEqual(987, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].baz) + self.assertEqual(654, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].Extensions[ + unittest_custom_options_pb2.grault]) + self.assertEqual(743, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].bar.foo) + self.assertEqual(1999, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].bar.Extensions[ + unittest_custom_options_pb2.quux]) + self.assertEqual(2008, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].bar.Extensions[ + unittest_custom_options_pb2.corge].qux) + self.assertEqual(741, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].Extensions[ + unittest_custom_options_pb2.garply].foo) + self.assertEqual(1998, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].Extensions[ + unittest_custom_options_pb2.garply].Extensions[ + unittest_custom_options_pb2.quux]) + self.assertEqual(2121, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].Extensions[ + unittest_custom_options_pb2.garply].Extensions[ + unittest_custom_options_pb2.corge].qux) + self.assertEqual(1971, options.Extensions[ + unittest_custom_options_pb2.ComplexOptionType2 + .ComplexOptionType4.complex_opt4].waldo) + self.assertEqual(321, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].fred.waldo) + self.assertEqual(9, options.Extensions[ + unittest_custom_options_pb2.complex_opt3].qux) + self.assertEqual(22, options.Extensions[ + unittest_custom_options_pb2.complex_opt3].complexoptiontype5.plugh) + self.assertEqual(24, options.Extensions[ + unittest_custom_options_pb2.complexopt6].xyzzy) + + # Check that aggregate options were parsed and saved correctly in + # the appropriate descriptors. + def testAggregateOptions(self): + file_descriptor = unittest_custom_options_pb2.DESCRIPTOR + message_descriptor =\ + unittest_custom_options_pb2.AggregateMessage.DESCRIPTOR + field_descriptor = message_descriptor.fields_by_name["fieldname"] + enum_descriptor = unittest_custom_options_pb2.AggregateEnum.DESCRIPTOR + enum_value_descriptor = enum_descriptor.values_by_name["VALUE"] + service_descriptor =\ + unittest_custom_options_pb2.AggregateService.DESCRIPTOR + method_descriptor = service_descriptor.FindMethodByName("Method") + + # Tests for the different types of data embedded in fileopt + file_options = file_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.fileopt] + self.assertEqual(100, file_options.i) + self.assertEqual("FileAnnotation", file_options.s) + self.assertEqual("NestedFileAnnotation", file_options.sub.s) + self.assertEqual("FileExtensionAnnotation", file_options.file.Extensions[ + unittest_custom_options_pb2.fileopt].s) + self.assertEqual("EmbeddedMessageSetElement", file_options.mset.Extensions[ + unittest_custom_options_pb2.AggregateMessageSetElement + .message_set_extension].s) + + # Simple tests for all the other types of annotations + self.assertEqual( + "MessageAnnotation", + message_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.msgopt].s) + self.assertEqual( + "FieldAnnotation", + field_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.fieldopt].s) + self.assertEqual( + "EnumAnnotation", + enum_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.enumopt].s) + self.assertEqual( + "EnumValueAnnotation", + enum_value_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.enumvalopt].s) + self.assertEqual( + "ServiceAnnotation", + service_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.serviceopt].s) + self.assertEqual( + "MethodAnnotation", + method_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.methodopt].s) + + def testNestedOptions(self): + nested_message =\ + unittest_custom_options_pb2.NestedOptionType.NestedMessage.DESCRIPTOR + self.assertEqual(1001, nested_message.GetOptions().Extensions[ + unittest_custom_options_pb2.message_opt1]) + nested_field = nested_message.fields_by_name["nested_field"] + self.assertEqual(1002, nested_field.GetOptions().Extensions[ + unittest_custom_options_pb2.field_opt1]) + outer_message =\ + unittest_custom_options_pb2.NestedOptionType.DESCRIPTOR + nested_enum = outer_message.enum_types_by_name["NestedEnum"] + self.assertEqual(1003, nested_enum.GetOptions().Extensions[ + unittest_custom_options_pb2.enum_opt1]) + nested_enum_value = outer_message.enum_values_by_name["NESTED_ENUM_VALUE"] + self.assertEqual(1004, nested_enum_value.GetOptions().Extensions[ + unittest_custom_options_pb2.enum_value_opt1]) + nested_extension = outer_message.extensions_by_name["nested_extension"] + self.assertEqual(1005, nested_extension.GetOptions().Extensions[ + unittest_custom_options_pb2.field_opt2]) + def testFileDescriptorReferences(self): self.assertEqual(self.my_enum.file, self.my_file) self.assertEqual(self.my_message.file, self.my_file) @@ -134,7 +395,7 @@ class DescriptorTest(unittest.TestCase): self.assertEqual(self.my_file.package, 'protobuf_unittest') -class DescriptorCopyToProtoTest(unittest.TestCase): +class DescriptorCopyToProtoTest(basetest.TestCase): """Tests for CopyTo functions of Descriptor.""" def _AssertProtoEqual(self, actual_proto, expected_class, expected_ascii): @@ -269,45 +530,49 @@ class DescriptorCopyToProtoTest(unittest.TestCase): descriptor_pb2.DescriptorProto, TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII) - def testCopyToProto_FileDescriptor(self): - UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = (""" - name: 'google/protobuf/unittest_import.proto' - package: 'protobuf_unittest_import' - message_type: < - name: 'ImportMessage' - field: < - name: 'd' - number: 1 - label: 1 # Optional - type: 5 # TYPE_INT32 - > - > - """ + - """enum_type: < - name: 'ImportEnum' - value: < - name: 'IMPORT_FOO' - number: 7 - > - value: < - name: 'IMPORT_BAR' - number: 8 - > - value: < - name: 'IMPORT_BAZ' - number: 9 - > - > - options: < - java_package: 'com.google.protobuf.test' - optimize_for: 1 # SPEED - > - """) - - self._InternalTestCopyToProto( - unittest_import_pb2.DESCRIPTOR, - descriptor_pb2.FileDescriptorProto, - UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII) + # Disable this test so we can make changes to the proto file. + # TODO(xiaofeng): Enable this test after cl/55530659 is submitted. + # + # def testCopyToProto_FileDescriptor(self): + # UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = (""" + # name: 'google/protobuf/unittest_import.proto' + # package: 'protobuf_unittest_import' + # dependency: 'google/protobuf/unittest_import_public.proto' + # message_type: < + # name: 'ImportMessage' + # field: < + # name: 'd' + # number: 1 + # label: 1 # Optional + # type: 5 # TYPE_INT32 + # > + # > + # """ + + # """enum_type: < + # name: 'ImportEnum' + # value: < + # name: 'IMPORT_FOO' + # number: 7 + # > + # value: < + # name: 'IMPORT_BAR' + # number: 8 + # > + # value: < + # name: 'IMPORT_BAZ' + # number: 9 + # > + # > + # options: < + # java_package: 'com.google.protobuf.test' + # optimize_for: 1 # SPEED + # > + # public_dependency: 0 + # """) + # self._InternalTestCopyToProto( + # unittest_import_pb2.DESCRIPTOR, + # descriptor_pb2.FileDescriptorProto, + # UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII) def testCopyToProto_ServiceDescriptor(self): TEST_SERVICE_ASCII = """ @@ -323,12 +588,82 @@ class DescriptorCopyToProtoTest(unittest.TestCase): output_type: '.protobuf_unittest.BarResponse' > """ - self._InternalTestCopyToProto( unittest_pb2.TestService.DESCRIPTOR, descriptor_pb2.ServiceDescriptorProto, TEST_SERVICE_ASCII) +class MakeDescriptorTest(basetest.TestCase): + + def testMakeDescriptorWithNestedFields(self): + file_descriptor_proto = descriptor_pb2.FileDescriptorProto() + file_descriptor_proto.name = 'Foo2' + message_type = file_descriptor_proto.message_type.add() + message_type.name = file_descriptor_proto.name + nested_type = message_type.nested_type.add() + nested_type.name = 'Sub' + enum_type = nested_type.enum_type.add() + enum_type.name = 'FOO' + enum_type_val = enum_type.value.add() + enum_type_val.name = 'BAR' + enum_type_val.number = 3 + field = message_type.field.add() + field.number = 1 + field.name = 'uint64_field' + field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + field.type = descriptor.FieldDescriptor.TYPE_UINT64 + field = message_type.field.add() + field.number = 2 + field.name = 'nested_message_field' + field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + field.type = descriptor.FieldDescriptor.TYPE_MESSAGE + field.type_name = 'Sub' + enum_field = nested_type.field.add() + enum_field.number = 2 + enum_field.name = 'bar_field' + enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM + enum_field.type_name = 'Foo2.Sub.FOO' + + result = descriptor.MakeDescriptor(message_type) + self.assertEqual(result.fields[0].cpp_type, + descriptor.FieldDescriptor.CPPTYPE_UINT64) + self.assertEqual(result.fields[1].cpp_type, + descriptor.FieldDescriptor.CPPTYPE_MESSAGE) + self.assertEqual(result.fields[1].message_type.containing_type, + result) + self.assertEqual(result.nested_types[0].fields[0].full_name, + 'Foo2.Sub.bar_field') + self.assertEqual(result.nested_types[0].fields[0].enum_type, + result.nested_types[0].enum_types[0]) + + def testMakeDescriptorWithUnsignedIntField(self): + file_descriptor_proto = descriptor_pb2.FileDescriptorProto() + file_descriptor_proto.name = 'Foo' + message_type = file_descriptor_proto.message_type.add() + message_type.name = file_descriptor_proto.name + enum_type = message_type.enum_type.add() + enum_type.name = 'FOO' + enum_type_val = enum_type.value.add() + enum_type_val.name = 'BAR' + enum_type_val.number = 3 + field = message_type.field.add() + field.number = 1 + field.name = 'uint64_field' + field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + field.type = descriptor.FieldDescriptor.TYPE_UINT64 + enum_field = message_type.field.add() + enum_field.number = 2 + enum_field.name = 'bar_field' + enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM + enum_field.type_name = 'Foo.FOO' + + result = descriptor.MakeDescriptor(message_type) + self.assertEqual(result.fields[0].cpp_type, + descriptor.FieldDescriptor.CPPTYPE_UINT64) + + if __name__ == '__main__': - unittest.main() + basetest.main() diff --git a/python/google/protobuf/internal/encoder.py b/python/google/protobuf/internal/encoder.py index aa05d5b..0a7c041 100755 --- a/python/google/protobuf/internal/encoder.py +++ b/python/google/protobuf/internal/encoder.py @@ -28,6 +28,10 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#PY25 compatible for GAE. +# +# Copyright 2009 Google Inc. All Rights Reserved. + """Code for encoding protocol message primitives. Contains the logic for encoding every logical protocol field type @@ -67,9 +71,17 @@ sizer rather than when calling them. In particular: __author__ = 'kenton@google.com (Kenton Varda)' import struct +import sys ##PY25 +_PY2 = sys.version_info[0] < 3 ##PY25 from google.protobuf.internal import wire_format +# This will overflow and thus become IEEE-754 "infinity". We would use +# "float('inf')" but it doesn't work on Windows pre-Python-2.6. +_POS_INF = 1e10000 +_NEG_INF = -_POS_INF + + def _VarintSize(value): """Compute the size of a varint value.""" if value <= 0x7f: return 1 @@ -334,7 +346,8 @@ def MessageSetItemSizer(field_number): def _VarintEncoder(): """Return an encoder for a basic varint value (does not include tag).""" - local_chr = chr + local_chr = _PY2 and chr or (lambda x: bytes((x,))) ##PY25 +##!PY25 local_chr = chr if bytes is str else lambda x: bytes((x,)) def EncodeVarint(write, value): bits = value & 0x7f value >>= 7 @@ -351,7 +364,8 @@ def _SignedVarintEncoder(): """Return an encoder for a basic signed varint value (does not include tag).""" - local_chr = chr + local_chr = _PY2 and chr or (lambda x: bytes((x,))) ##PY25 +##!PY25 local_chr = chr if bytes is str else lambda x: bytes((x,)) def EncodeSignedVarint(write, value): if value < 0: value += (1 << 64) @@ -376,7 +390,8 @@ def _VarintBytes(value): pieces = [] _EncodeVarint(pieces.append, value) - return "".join(pieces) + return "".encode("latin1").join(pieces) ##PY25 +##!PY25 return b"".join(pieces) def TagBytes(field_number, wire_type): @@ -502,6 +517,90 @@ def _StructPackEncoder(wire_type, format): return SpecificEncoder +def _FloatingPointEncoder(wire_type, format): + """Return a constructor for an encoder for float fields. + + This is like StructPackEncoder, but catches errors that may be due to + passing non-finite floating-point values to struct.pack, and makes a + second attempt to encode those values. + + Args: + wire_type: The field's wire type, for encoding tags. + format: The format string to pass to struct.pack(). + """ + + b = _PY2 and (lambda x:x) or (lambda x:x.encode('latin1')) ##PY25 + value_size = struct.calcsize(format) + if value_size == 4: + def EncodeNonFiniteOrRaise(write, value): + # Remember that the serialized form uses little-endian byte order. + if value == _POS_INF: + write(b('\x00\x00\x80\x7F')) ##PY25 +##!PY25 write(b'\x00\x00\x80\x7F') + elif value == _NEG_INF: + write(b('\x00\x00\x80\xFF')) ##PY25 +##!PY25 write(b'\x00\x00\x80\xFF') + elif value != value: # NaN + write(b('\x00\x00\xC0\x7F')) ##PY25 +##!PY25 write(b'\x00\x00\xC0\x7F') + else: + raise + elif value_size == 8: + def EncodeNonFiniteOrRaise(write, value): + if value == _POS_INF: + write(b('\x00\x00\x00\x00\x00\x00\xF0\x7F')) ##PY25 +##!PY25 write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F') + elif value == _NEG_INF: + write(b('\x00\x00\x00\x00\x00\x00\xF0\xFF')) ##PY25 +##!PY25 write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF') + elif value != value: # NaN + write(b('\x00\x00\x00\x00\x00\x00\xF8\x7F')) ##PY25 +##!PY25 write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F') + else: + raise + else: + raise ValueError('Can\'t encode floating-point values that are ' + '%d bytes long (only 4 or 8)' % value_size) + + def SpecificEncoder(field_number, is_repeated, is_packed): + local_struct_pack = struct.pack + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value): + write(tag_bytes) + local_EncodeVarint(write, len(value) * value_size) + for element in value: + # This try/except block is going to be faster than any code that + # we could write to check whether element is finite. + try: + write(local_struct_pack(format, element)) + except SystemError: + EncodeNonFiniteOrRaise(write, element) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value): + for element in value: + write(tag_bytes) + try: + write(local_struct_pack(format, element)) + except SystemError: + EncodeNonFiniteOrRaise(write, element) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value): + write(tag_bytes) + try: + write(local_struct_pack(format, value)) + except SystemError: + EncodeNonFiniteOrRaise(write, value) + return EncodeField + + return SpecificEncoder + + # ==================================================================== # Here we declare an encoder constructor for each field type. These work # very similarly to sizer constructors, described earlier. @@ -525,15 +624,17 @@ Fixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, ' 0) +def IsNegInf(val): + return isinf(val) and (val < 0) -class MessageTest(unittest.TestCase): +class MessageTest(basetest.TestCase): + + def testBadUtf8String(self): + if api_implementation.Type() != 'python': + self.skipTest("Skipping testBadUtf8String, currently only the python " + "api implementation raises UnicodeDecodeError when a " + "string field contains bad utf-8.") + bad_utf8_data = test_util.GoldenFileData('bad_utf8_string') + with self.assertRaises(UnicodeDecodeError) as context: + unittest_pb2.TestAllTypes.FromString(bad_utf8_data) + self.assertIn('field: protobuf_unittest.TestAllTypes.optional_string', + str(context.exception)) def testGoldenMessage(self): - golden_data = test_util.GoldenFile('golden_message').read() + golden_data = test_util.GoldenFileData( + 'golden_message_oneof_implemented') golden_message = unittest_pb2.TestAllTypes() golden_message.ParseFromString(golden_data) test_util.ExpectAllFieldsSet(self, golden_message) - self.assertTrue(golden_message.SerializeToString() == golden_data) + self.assertEqual(golden_data, golden_message.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) def testGoldenExtensions(self): - golden_data = test_util.GoldenFile('golden_message').read() + golden_data = test_util.GoldenFileData('golden_message') golden_message = unittest_pb2.TestAllExtensions() golden_message.ParseFromString(golden_data) all_set = unittest_pb2.TestAllExtensions() test_util.SetAllExtensions(all_set) self.assertEquals(all_set, golden_message) - self.assertTrue(golden_message.SerializeToString() == golden_data) + self.assertEqual(golden_data, golden_message.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) def testGoldenPackedMessage(self): - golden_data = test_util.GoldenFile('golden_packed_fields_message').read() + golden_data = test_util.GoldenFileData('golden_packed_fields_message') golden_message = unittest_pb2.TestPackedTypes() golden_message.ParseFromString(golden_data) all_set = unittest_pb2.TestPackedTypes() test_util.SetAllPackedFields(all_set) self.assertEquals(all_set, golden_message) - self.assertTrue(all_set.SerializeToString() == golden_data) + self.assertEqual(golden_data, all_set.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) def testGoldenPackedExtensions(self): - golden_data = test_util.GoldenFile('golden_packed_fields_message').read() + golden_data = test_util.GoldenFileData('golden_packed_fields_message') golden_message = unittest_pb2.TestPackedExtensions() golden_message.ParseFromString(golden_data) all_set = unittest_pb2.TestPackedExtensions() test_util.SetAllPackedExtensions(all_set) self.assertEquals(all_set, golden_message) - self.assertTrue(all_set.SerializeToString() == golden_data) + self.assertEqual(golden_data, all_set.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) + + def testPickleSupport(self): + golden_data = test_util.GoldenFileData('golden_message') + golden_message = unittest_pb2.TestAllTypes() + golden_message.ParseFromString(golden_data) + pickled_message = pickle.dumps(golden_message) + + unpickled_message = pickle.loads(pickled_message) + self.assertEquals(unpickled_message, golden_message) + + + def testPickleIncompleteProto(self): + golden_message = unittest_pb2.TestRequired(a=1) + pickled_message = pickle.dumps(golden_message) + + unpickled_message = pickle.loads(pickled_message) + self.assertEquals(unpickled_message, golden_message) + self.assertEquals(unpickled_message.a, 1) + # This is still an incomplete proto - so serializing should fail + self.assertRaises(message.EncodeError, unpickled_message.SerializeToString) + + def testPositiveInfinity(self): + golden_data = (b'\x5D\x00\x00\x80\x7F' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F' + b'\xCD\x02\x00\x00\x80\x7F' + b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F') + golden_message = unittest_pb2.TestAllTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(IsPosInf(golden_message.optional_float)) + self.assertTrue(IsPosInf(golden_message.optional_double)) + self.assertTrue(IsPosInf(golden_message.repeated_float[0])) + self.assertTrue(IsPosInf(golden_message.repeated_double[0])) + self.assertEqual(golden_data, golden_message.SerializeToString()) + + def testNegativeInfinity(self): + golden_data = (b'\x5D\x00\x00\x80\xFF' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF' + b'\xCD\x02\x00\x00\x80\xFF' + b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF') + golden_message = unittest_pb2.TestAllTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(IsNegInf(golden_message.optional_float)) + self.assertTrue(IsNegInf(golden_message.optional_double)) + self.assertTrue(IsNegInf(golden_message.repeated_float[0])) + self.assertTrue(IsNegInf(golden_message.repeated_double[0])) + self.assertEqual(golden_data, golden_message.SerializeToString()) + + def testNotANumber(self): + golden_data = (b'\x5D\x00\x00\xC0\x7F' + b'\x61\x00\x00\x00\x00\x00\x00\xF8\x7F' + b'\xCD\x02\x00\x00\xC0\x7F' + b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F') + golden_message = unittest_pb2.TestAllTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(isnan(golden_message.optional_float)) + self.assertTrue(isnan(golden_message.optional_double)) + self.assertTrue(isnan(golden_message.repeated_float[0])) + self.assertTrue(isnan(golden_message.repeated_double[0])) + + # The protocol buffer may serialize to any one of multiple different + # representations of a NaN. Rather than verify a specific representation, + # verify the serialized string can be converted into a correctly + # behaving protocol buffer. + serialized = golden_message.SerializeToString() + message = unittest_pb2.TestAllTypes() + message.ParseFromString(serialized) + self.assertTrue(isnan(message.optional_float)) + self.assertTrue(isnan(message.optional_double)) + self.assertTrue(isnan(message.repeated_float[0])) + self.assertTrue(isnan(message.repeated_double[0])) + + def testPositiveInfinityPacked(self): + golden_data = (b'\xA2\x06\x04\x00\x00\x80\x7F' + b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F') + golden_message = unittest_pb2.TestPackedTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(IsPosInf(golden_message.packed_float[0])) + self.assertTrue(IsPosInf(golden_message.packed_double[0])) + self.assertEqual(golden_data, golden_message.SerializeToString()) + + def testNegativeInfinityPacked(self): + golden_data = (b'\xA2\x06\x04\x00\x00\x80\xFF' + b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF') + golden_message = unittest_pb2.TestPackedTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(IsNegInf(golden_message.packed_float[0])) + self.assertTrue(IsNegInf(golden_message.packed_double[0])) + self.assertEqual(golden_data, golden_message.SerializeToString()) + + def testNotANumberPacked(self): + golden_data = (b'\xA2\x06\x04\x00\x00\xC0\x7F' + b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F') + golden_message = unittest_pb2.TestPackedTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(isnan(golden_message.packed_float[0])) + self.assertTrue(isnan(golden_message.packed_double[0])) + + serialized = golden_message.SerializeToString() + message = unittest_pb2.TestPackedTypes() + message.ParseFromString(serialized) + self.assertTrue(isnan(message.packed_float[0])) + self.assertTrue(isnan(message.packed_double[0])) + + def testExtremeFloatValues(self): + message = unittest_pb2.TestAllTypes() + + # Most positive exponent, no significand bits set. + kMostPosExponentNoSigBits = math.pow(2, 127) + message.optional_float = kMostPosExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == kMostPosExponentNoSigBits) + + # Most positive exponent, one significand bit set. + kMostPosExponentOneSigBit = 1.5 * math.pow(2, 127) + message.optional_float = kMostPosExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == kMostPosExponentOneSigBit) + + # Repeat last two cases with values of same magnitude, but negative. + message.optional_float = -kMostPosExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == -kMostPosExponentNoSigBits) + + message.optional_float = -kMostPosExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == -kMostPosExponentOneSigBit) + + # Most negative exponent, no significand bits set. + kMostNegExponentNoSigBits = math.pow(2, -127) + message.optional_float = kMostNegExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == kMostNegExponentNoSigBits) + + # Most negative exponent, one significand bit set. + kMostNegExponentOneSigBit = 1.5 * math.pow(2, -127) + message.optional_float = kMostNegExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == kMostNegExponentOneSigBit) + + # Repeat last two cases with values of the same magnitude, but negative. + message.optional_float = -kMostNegExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == -kMostNegExponentNoSigBits) + + message.optional_float = -kMostNegExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit) + + def testExtremeDoubleValues(self): + message = unittest_pb2.TestAllTypes() + + # Most positive exponent, no significand bits set. + kMostPosExponentNoSigBits = math.pow(2, 1023) + message.optional_double = kMostPosExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == kMostPosExponentNoSigBits) + + # Most positive exponent, one significand bit set. + kMostPosExponentOneSigBit = 1.5 * math.pow(2, 1023) + message.optional_double = kMostPosExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == kMostPosExponentOneSigBit) + + # Repeat last two cases with values of same magnitude, but negative. + message.optional_double = -kMostPosExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == -kMostPosExponentNoSigBits) + + message.optional_double = -kMostPosExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == -kMostPosExponentOneSigBit) + + # Most negative exponent, no significand bits set. + kMostNegExponentNoSigBits = math.pow(2, -1023) + message.optional_double = kMostNegExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == kMostNegExponentNoSigBits) + + # Most negative exponent, one significand bit set. + kMostNegExponentOneSigBit = 1.5 * math.pow(2, -1023) + message.optional_double = kMostNegExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == kMostNegExponentOneSigBit) + + # Repeat last two cases with values of the same magnitude, but negative. + message.optional_double = -kMostNegExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == -kMostNegExponentNoSigBits) + + message.optional_double = -kMostNegExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit) + + def testFloatPrinting(self): + message = unittest_pb2.TestAllTypes() + message.optional_float = 2.0 + self.assertEqual(str(message), 'optional_float: 2.0\n') + + def testHighPrecisionFloatPrinting(self): + message = unittest_pb2.TestAllTypes() + message.optional_double = 0.12345678912345678 + if sys.version_info.major >= 3: + self.assertEqual(str(message), 'optional_double: 0.12345678912345678\n') + else: + self.assertEqual(str(message), 'optional_double: 0.123456789123\n') + + def testUnknownFieldPrinting(self): + populated = unittest_pb2.TestAllTypes() + test_util.SetAllNonLazyFields(populated) + empty = unittest_pb2.TestEmptyMessage() + empty.ParseFromString(populated.SerializeToString()) + self.assertEqual(str(empty), '') + + def testSortingRepeatedScalarFieldsDefaultComparator(self): + """Check some different types with the default comparator.""" + message = unittest_pb2.TestAllTypes() + + # TODO(mattp): would testing more scalar types strengthen test? + message.repeated_int32.append(1) + message.repeated_int32.append(3) + message.repeated_int32.append(2) + message.repeated_int32.sort() + self.assertEqual(message.repeated_int32[0], 1) + self.assertEqual(message.repeated_int32[1], 2) + self.assertEqual(message.repeated_int32[2], 3) + + message.repeated_float.append(1.1) + message.repeated_float.append(1.3) + message.repeated_float.append(1.2) + message.repeated_float.sort() + self.assertAlmostEqual(message.repeated_float[0], 1.1) + self.assertAlmostEqual(message.repeated_float[1], 1.2) + self.assertAlmostEqual(message.repeated_float[2], 1.3) + + message.repeated_string.append('a') + message.repeated_string.append('c') + message.repeated_string.append('b') + message.repeated_string.sort() + self.assertEqual(message.repeated_string[0], 'a') + self.assertEqual(message.repeated_string[1], 'b') + self.assertEqual(message.repeated_string[2], 'c') + + message.repeated_bytes.append(b'a') + message.repeated_bytes.append(b'c') + message.repeated_bytes.append(b'b') + message.repeated_bytes.sort() + self.assertEqual(message.repeated_bytes[0], b'a') + self.assertEqual(message.repeated_bytes[1], b'b') + self.assertEqual(message.repeated_bytes[2], b'c') + + def testSortingRepeatedScalarFieldsCustomComparator(self): + """Check some different types with custom comparator.""" + message = unittest_pb2.TestAllTypes() + + message.repeated_int32.append(-3) + message.repeated_int32.append(-2) + message.repeated_int32.append(-1) + message.repeated_int32.sort(key=abs) + self.assertEqual(message.repeated_int32[0], -1) + self.assertEqual(message.repeated_int32[1], -2) + self.assertEqual(message.repeated_int32[2], -3) + + message.repeated_string.append('aaa') + message.repeated_string.append('bb') + message.repeated_string.append('c') + message.repeated_string.sort(key=len) + self.assertEqual(message.repeated_string[0], 'c') + self.assertEqual(message.repeated_string[1], 'bb') + self.assertEqual(message.repeated_string[2], 'aaa') + + def testSortingRepeatedCompositeFieldsCustomComparator(self): + """Check passing a custom comparator to sort a repeated composite field.""" + message = unittest_pb2.TestAllTypes() + + message.repeated_nested_message.add().bb = 1 + message.repeated_nested_message.add().bb = 3 + message.repeated_nested_message.add().bb = 2 + message.repeated_nested_message.add().bb = 6 + message.repeated_nested_message.add().bb = 5 + message.repeated_nested_message.add().bb = 4 + message.repeated_nested_message.sort(key=operator.attrgetter('bb')) + self.assertEqual(message.repeated_nested_message[0].bb, 1) + self.assertEqual(message.repeated_nested_message[1].bb, 2) + self.assertEqual(message.repeated_nested_message[2].bb, 3) + self.assertEqual(message.repeated_nested_message[3].bb, 4) + self.assertEqual(message.repeated_nested_message[4].bb, 5) + self.assertEqual(message.repeated_nested_message[5].bb, 6) + + def testRepeatedCompositeFieldSortArguments(self): + """Check sorting a repeated composite field using list.sort() arguments.""" + message = unittest_pb2.TestAllTypes() + + get_bb = operator.attrgetter('bb') + cmp_bb = lambda a, b: cmp(a.bb, b.bb) + message.repeated_nested_message.add().bb = 1 + message.repeated_nested_message.add().bb = 3 + message.repeated_nested_message.add().bb = 2 + message.repeated_nested_message.add().bb = 6 + message.repeated_nested_message.add().bb = 5 + message.repeated_nested_message.add().bb = 4 + message.repeated_nested_message.sort(key=get_bb) + self.assertEqual([k.bb for k in message.repeated_nested_message], + [1, 2, 3, 4, 5, 6]) + message.repeated_nested_message.sort(key=get_bb, reverse=True) + self.assertEqual([k.bb for k in message.repeated_nested_message], + [6, 5, 4, 3, 2, 1]) + if sys.version_info.major >= 3: return # No cmp sorting in PY3. + message.repeated_nested_message.sort(sort_function=cmp_bb) + self.assertEqual([k.bb for k in message.repeated_nested_message], + [1, 2, 3, 4, 5, 6]) + message.repeated_nested_message.sort(cmp=cmp_bb, reverse=True) + self.assertEqual([k.bb for k in message.repeated_nested_message], + [6, 5, 4, 3, 2, 1]) + + def testRepeatedScalarFieldSortArguments(self): + """Check sorting a scalar field using list.sort() arguments.""" + message = unittest_pb2.TestAllTypes() + + message.repeated_int32.append(-3) + message.repeated_int32.append(-2) + message.repeated_int32.append(-1) + message.repeated_int32.sort(key=abs) + self.assertEqual(list(message.repeated_int32), [-1, -2, -3]) + message.repeated_int32.sort(key=abs, reverse=True) + self.assertEqual(list(message.repeated_int32), [-3, -2, -1]) + if sys.version_info.major < 3: # No cmp sorting in PY3. + abs_cmp = lambda a, b: cmp(abs(a), abs(b)) + message.repeated_int32.sort(sort_function=abs_cmp) + self.assertEqual(list(message.repeated_int32), [-1, -2, -3]) + message.repeated_int32.sort(cmp=abs_cmp, reverse=True) + self.assertEqual(list(message.repeated_int32), [-3, -2, -1]) + + message.repeated_string.append('aaa') + message.repeated_string.append('bb') + message.repeated_string.append('c') + message.repeated_string.sort(key=len) + self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa']) + message.repeated_string.sort(key=len, reverse=True) + self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c']) + if sys.version_info.major < 3: # No cmp sorting in PY3. + len_cmp = lambda a, b: cmp(len(a), len(b)) + message.repeated_string.sort(sort_function=len_cmp) + self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa']) + message.repeated_string.sort(cmp=len_cmp, reverse=True) + self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c']) + + def testRepeatedFieldsComparable(self): + m1 = unittest_pb2.TestAllTypes() + m2 = unittest_pb2.TestAllTypes() + m1.repeated_int32.append(0) + m1.repeated_int32.append(1) + m1.repeated_int32.append(2) + m2.repeated_int32.append(0) + m2.repeated_int32.append(1) + m2.repeated_int32.append(2) + m1.repeated_nested_message.add().bb = 1 + m1.repeated_nested_message.add().bb = 2 + m1.repeated_nested_message.add().bb = 3 + m2.repeated_nested_message.add().bb = 1 + m2.repeated_nested_message.add().bb = 2 + m2.repeated_nested_message.add().bb = 3 + + if sys.version_info.major >= 3: return # No cmp() in PY3. + + # These comparisons should not raise errors. + _ = m1 < m2 + _ = m1.repeated_nested_message < m2.repeated_nested_message + + # Make sure cmp always works. If it wasn't defined, these would be + # id() comparisons and would all fail. + self.assertEqual(cmp(m1, m2), 0) + self.assertEqual(cmp(m1.repeated_int32, m2.repeated_int32), 0) + self.assertEqual(cmp(m1.repeated_int32, [0, 1, 2]), 0) + self.assertEqual(cmp(m1.repeated_nested_message, + m2.repeated_nested_message), 0) + with self.assertRaises(TypeError): + # Can't compare repeated composite containers to lists. + cmp(m1.repeated_nested_message, m2.repeated_nested_message[:]) + + # TODO(anuraag): Implement extensiondict comparison in C++ and then add test + + def testParsingMerge(self): + """Check the merge behavior when a required or optional field appears + multiple times in the input.""" + messages = [ + unittest_pb2.TestAllTypes(), + unittest_pb2.TestAllTypes(), + unittest_pb2.TestAllTypes() ] + messages[0].optional_int32 = 1 + messages[1].optional_int64 = 2 + messages[2].optional_int32 = 3 + messages[2].optional_string = 'hello' + + merged_message = unittest_pb2.TestAllTypes() + merged_message.optional_int32 = 3 + merged_message.optional_int64 = 2 + merged_message.optional_string = 'hello' + + generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator() + generator.field1.extend(messages) + generator.field2.extend(messages) + generator.field3.extend(messages) + generator.ext1.extend(messages) + generator.ext2.extend(messages) + generator.group1.add().field1.MergeFrom(messages[0]) + generator.group1.add().field1.MergeFrom(messages[1]) + generator.group1.add().field1.MergeFrom(messages[2]) + generator.group2.add().field1.MergeFrom(messages[0]) + generator.group2.add().field1.MergeFrom(messages[1]) + generator.group2.add().field1.MergeFrom(messages[2]) + + data = generator.SerializeToString() + parsing_merge = unittest_pb2.TestParsingMerge() + parsing_merge.ParseFromString(data) + + # Required and optional fields should be merged. + self.assertEqual(parsing_merge.required_all_types, merged_message) + self.assertEqual(parsing_merge.optional_all_types, merged_message) + self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types, + merged_message) + self.assertEqual(parsing_merge.Extensions[ + unittest_pb2.TestParsingMerge.optional_ext], + merged_message) + + # Repeated fields should not be merged. + self.assertEqual(len(parsing_merge.repeated_all_types), 3) + self.assertEqual(len(parsing_merge.repeatedgroup), 3) + self.assertEqual(len(parsing_merge.Extensions[ + unittest_pb2.TestParsingMerge.repeated_ext]), 3) + + def ensureNestedMessageExists(self, msg, attribute): + """Make sure that a nested message object exists. + + As soon as a nested message attribute is accessed, it will be present in the + _fields dict, without being marked as actually being set. + """ + getattr(msg, attribute) + self.assertFalse(msg.HasField(attribute)) + + def testOneofGetCaseNonexistingField(self): + m = unittest_pb2.TestAllTypes() + self.assertRaises(ValueError, m.WhichOneof, 'no_such_oneof_field') + + def testOneofSemantics(self): + m = unittest_pb2.TestAllTypes() + self.assertIs(None, m.WhichOneof('oneof_field')) + + m.oneof_uint32 = 11 + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_uint32')) + + m.oneof_string = u'foo' + self.assertEqual('oneof_string', m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_uint32')) + self.assertTrue(m.HasField('oneof_string')) + + m.oneof_nested_message.bb = 11 + self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_string')) + self.assertTrue(m.HasField('oneof_nested_message')) + + m.oneof_bytes = b'bb' + self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_nested_message')) + self.assertTrue(m.HasField('oneof_bytes')) + + def testOneofCompositeFieldReadAccess(self): + m = unittest_pb2.TestAllTypes() + m.oneof_uint32 = 11 + + self.ensureNestedMessageExists(m, 'oneof_nested_message') + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + self.assertEqual(11, m.oneof_uint32) + + def testOneofHasField(self): + m = unittest_pb2.TestAllTypes() + self.assertFalse(m.HasField('oneof_field')) + m.oneof_uint32 = 11 + self.assertTrue(m.HasField('oneof_field')) + m.oneof_bytes = b'bb' + self.assertTrue(m.HasField('oneof_field')) + m.ClearField('oneof_bytes') + self.assertFalse(m.HasField('oneof_field')) + + def testOneofClearField(self): + m = unittest_pb2.TestAllTypes() + m.oneof_uint32 = 11 + m.ClearField('oneof_field') + self.assertFalse(m.HasField('oneof_field')) + self.assertFalse(m.HasField('oneof_uint32')) + self.assertIs(None, m.WhichOneof('oneof_field')) + + def testOneofClearSetField(self): + m = unittest_pb2.TestAllTypes() + m.oneof_uint32 = 11 + m.ClearField('oneof_uint32') + self.assertFalse(m.HasField('oneof_field')) + self.assertFalse(m.HasField('oneof_uint32')) + self.assertIs(None, m.WhichOneof('oneof_field')) + + def testOneofClearUnsetField(self): + m = unittest_pb2.TestAllTypes() + m.oneof_uint32 = 11 + self.ensureNestedMessageExists(m, 'oneof_nested_message') + m.ClearField('oneof_nested_message') + self.assertEqual(11, m.oneof_uint32) + self.assertTrue(m.HasField('oneof_field')) + self.assertTrue(m.HasField('oneof_uint32')) + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + + + + def testSortEmptyRepeatedCompositeContainer(self): + """Exercise a scenario that has led to segfaults in the past. + """ + m = unittest_pb2.TestAllTypes() + m.repeated_nested_message.sort() + + def testHasFieldOnRepeatedField(self): + """Using HasField on a repeated field should raise an exception. + """ + m = unittest_pb2.TestAllTypes() + with self.assertRaises(ValueError) as _: + m.HasField('repeated_int32') + + +class ValidTypeNamesTest(basetest.TestCase): + + def assertImportFromName(self, msg, base_name): + # Parse to extra 'some.name' as a string. + tp_name = str(type(msg)).split("'")[1] + valid_names = ('Repeated%sContainer' % base_name, + 'Repeated%sFieldContainer' % base_name) + self.assertTrue(any(tp_name.endswith(v) for v in valid_names), + '%r does end with any of %r' % (tp_name, valid_names)) + + parts = tp_name.split('.') + class_name = parts[-1] + module_name = '.'.join(parts[:-1]) + __import__(module_name, fromlist=[class_name]) + + def testTypeNamesCanBeImported(self): + # If import doesn't work, pickling won't work either. + pb = unittest_pb2.TestAllTypes() + self.assertImportFromName(pb.repeated_int32, 'Scalar') + self.assertImportFromName(pb.repeated_nested_message, 'Composite') + if __name__ == '__main__': - unittest.main() + basetest.main() diff --git a/python/google/protobuf/internal/missing_enum_values.proto b/python/google/protobuf/internal/missing_enum_values.proto new file mode 100644 index 0000000..c9ae58b --- /dev/null +++ b/python/google/protobuf/internal/missing_enum_values.proto @@ -0,0 +1,50 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package google.protobuf.python.internal; + +message TestEnumValues { + enum NestedEnum { + ZERO = 0; + ONE = 1; + } + optional NestedEnum optional_nested_enum = 1; + repeated NestedEnum repeated_nested_enum = 2; + repeated NestedEnum packed_nested_enum = 3 [packed = true]; +} + +message TestMissingEnumValues { + enum NestedEnum { + TWO = 2; + } + optional NestedEnum optional_nested_enum = 1; + repeated NestedEnum repeated_nested_enum = 2; + repeated NestedEnum packed_nested_enum = 3 [packed = true]; +} diff --git a/python/google/protobuf/internal/more_extensions_dynamic.proto b/python/google/protobuf/internal/more_extensions_dynamic.proto new file mode 100644 index 0000000..df98ac4 --- /dev/null +++ b/python/google/protobuf/internal/more_extensions_dynamic.proto @@ -0,0 +1,49 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: jasonh@google.com (Jason Hsueh) +// +// This file is used to test a corner case in the CPP implementation where the +// generated C++ type is available for the extendee, but the extension is +// defined in a file whose C++ type is not in the binary. + + +import "google/protobuf/internal/more_extensions.proto"; + +package google.protobuf.internal; + +message DynamicMessageType { + optional int32 a = 1; +} + +extend ExtendedMessage { + optional int32 dynamic_int32_extension = 100; + optional DynamicMessageType dynamic_message_extension = 101; +} diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py new file mode 100755 index 0000000..9ee352d --- /dev/null +++ b/python/google/protobuf/internal/python_message.py @@ -0,0 +1,1247 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +# Keep it Python2.5 compatible for GAE. +# +# Copyright 2007 Google Inc. All Rights Reserved. +# +# This code is meant to work on Python 2.4 and above only. +# +# TODO(robinson): Helpers for verbose, common checks like seeing if a +# descriptor's cpp_type is CPPTYPE_MESSAGE. + +"""Contains a metaclass and helper functions used to create +protocol message classes from Descriptor objects at runtime. + +Recall that a metaclass is the "type" of a class. +(A class is to a metaclass what an instance is to a class.) + +In this case, we use the GeneratedProtocolMessageType metaclass +to inject all the useful functionality into the classes +output by the protocol compiler at compile-time. + +The upshot of all this is that the real implementation +details for ALL pure-Python protocol buffers are *here in +this file*. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import sys +if sys.version_info[0] < 3: + try: + from cStringIO import StringIO as BytesIO + except ImportError: + from StringIO import StringIO as BytesIO + import copy_reg as copyreg +else: + from io import BytesIO + import copyreg +import struct +import weakref + +# We use "as" to avoid name collisions with variables. +from google.protobuf.internal import containers +from google.protobuf.internal import decoder +from google.protobuf.internal import encoder +from google.protobuf.internal import enum_type_wrapper +from google.protobuf.internal import message_listener as message_listener_mod +from google.protobuf.internal import type_checkers +from google.protobuf.internal import wire_format +from google.protobuf import descriptor as descriptor_mod +from google.protobuf import message as message_mod +from google.protobuf import text_format + +_FieldDescriptor = descriptor_mod.FieldDescriptor + + +def NewMessage(bases, descriptor, dictionary): + _AddClassAttributesForNestedExtensions(descriptor, dictionary) + _AddSlots(descriptor, dictionary) + return bases + + +def InitMessage(descriptor, cls): + cls._decoders_by_tag = {} + cls._extensions_by_name = {} + cls._extensions_by_number = {} + if (descriptor.has_options and + descriptor.GetOptions().message_set_wire_format): + cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = ( + decoder.MessageSetItemDecoder(cls._extensions_by_number)) + + # Attach stuff to each FieldDescriptor for quick lookup later on. + for field in descriptor.fields: + _AttachFieldHelpers(cls, field) + + _AddEnumValues(descriptor, cls) + _AddInitMethod(descriptor, cls) + _AddPropertiesForFields(descriptor, cls) + _AddPropertiesForExtensions(descriptor, cls) + _AddStaticMethods(cls) + _AddMessageMethods(descriptor, cls) + _AddPrivateHelperMethods(descriptor, cls) + copyreg.pickle(cls, lambda obj: (cls, (), obj.__getstate__())) + + +# Stateless helpers for GeneratedProtocolMessageType below. +# Outside clients should not access these directly. +# +# I opted not to make any of these methods on the metaclass, to make it more +# clear that I'm not really using any state there and to keep clients from +# thinking that they have direct access to these construction helpers. + + +def _PropertyName(proto_field_name): + """Returns the name of the public property attribute which + clients can use to get and (in some cases) set the value + of a protocol message field. + + Args: + proto_field_name: The protocol message field name, exactly + as it appears (or would appear) in a .proto file. + """ + # TODO(robinson): Escape Python keywords (e.g., yield), and test this support. + # nnorwitz makes my day by writing: + # """ + # FYI. See the keyword module in the stdlib. This could be as simple as: + # + # if keyword.iskeyword(proto_field_name): + # return proto_field_name + "_" + # return proto_field_name + # """ + # Kenton says: The above is a BAD IDEA. People rely on being able to use + # getattr() and setattr() to reflectively manipulate field values. If we + # rename the properties, then every such user has to also make sure to apply + # the same transformation. Note that currently if you name a field "yield", + # you can still access it just fine using getattr/setattr -- it's not even + # that cumbersome to do so. + # TODO(kenton): Remove this method entirely if/when everyone agrees with my + # position. + return proto_field_name + + +def _VerifyExtensionHandle(message, extension_handle): + """Verify that the given extension handle is valid.""" + + if not isinstance(extension_handle, _FieldDescriptor): + raise KeyError('HasExtension() expects an extension handle, got: %s' % + extension_handle) + + if not extension_handle.is_extension: + raise KeyError('"%s" is not an extension.' % extension_handle.full_name) + + if not extension_handle.containing_type: + raise KeyError('"%s" is missing a containing_type.' + % extension_handle.full_name) + + if extension_handle.containing_type is not message.DESCRIPTOR: + raise KeyError('Extension "%s" extends message type "%s", but this ' + 'message is of type "%s".' % + (extension_handle.full_name, + extension_handle.containing_type.full_name, + message.DESCRIPTOR.full_name)) + + +def _AddSlots(message_descriptor, dictionary): + """Adds a __slots__ entry to dictionary, containing the names of all valid + attributes for this message type. + + Args: + message_descriptor: A Descriptor instance describing this message type. + dictionary: Class dictionary to which we'll add a '__slots__' entry. + """ + dictionary['__slots__'] = ['_cached_byte_size', + '_cached_byte_size_dirty', + '_fields', + '_unknown_fields', + '_is_present_in_parent', + '_listener', + '_listener_for_children', + '__weakref__', + '_oneofs'] + + +def _IsMessageSetExtension(field): + return (field.is_extension and + field.containing_type.has_options and + field.containing_type.GetOptions().message_set_wire_format and + field.type == _FieldDescriptor.TYPE_MESSAGE and + field.message_type == field.extension_scope and + field.label == _FieldDescriptor.LABEL_OPTIONAL) + + +def _AttachFieldHelpers(cls, field_descriptor): + is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED) + is_packed = (field_descriptor.has_options and + field_descriptor.GetOptions().packed) + + if _IsMessageSetExtension(field_descriptor): + field_encoder = encoder.MessageSetItemEncoder(field_descriptor.number) + sizer = encoder.MessageSetItemSizer(field_descriptor.number) + else: + field_encoder = type_checkers.TYPE_TO_ENCODER[field_descriptor.type]( + field_descriptor.number, is_repeated, is_packed) + sizer = type_checkers.TYPE_TO_SIZER[field_descriptor.type]( + field_descriptor.number, is_repeated, is_packed) + + field_descriptor._encoder = field_encoder + field_descriptor._sizer = sizer + field_descriptor._default_constructor = _DefaultValueConstructorForField( + field_descriptor) + + def AddDecoder(wiretype, is_packed): + tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype) + cls._decoders_by_tag[tag_bytes] = ( + type_checkers.TYPE_TO_DECODER[field_descriptor.type]( + field_descriptor.number, is_repeated, is_packed, + field_descriptor, field_descriptor._default_constructor)) + + AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type], + False) + + if is_repeated and wire_format.IsTypePackable(field_descriptor.type): + # To support wire compatibility of adding packed = true, add a decoder for + # packed values regardless of the field's options. + AddDecoder(wire_format.WIRETYPE_LENGTH_DELIMITED, True) + + +def _AddClassAttributesForNestedExtensions(descriptor, dictionary): + extension_dict = descriptor.extensions_by_name + for extension_name, extension_field in extension_dict.iteritems(): + assert extension_name not in dictionary + dictionary[extension_name] = extension_field + + +def _AddEnumValues(descriptor, cls): + """Sets class-level attributes for all enum fields defined in this message. + + Also exporting a class-level object that can name enum values. + + Args: + descriptor: Descriptor object for this message type. + cls: Class we're constructing for this message type. + """ + for enum_type in descriptor.enum_types: + setattr(cls, enum_type.name, enum_type_wrapper.EnumTypeWrapper(enum_type)) + for enum_value in enum_type.values: + setattr(cls, enum_value.name, enum_value.number) + + +def _DefaultValueConstructorForField(field): + """Returns a function which returns a default value for a field. + + Args: + field: FieldDescriptor object for this field. + + The returned function has one argument: + message: Message instance containing this field, or a weakref proxy + of same. + + That function in turn returns a default value for this field. The default + value may refer back to |message| via a weak reference. + """ + + if field.label == _FieldDescriptor.LABEL_REPEATED: + if field.has_default_value and field.default_value != []: + raise ValueError('Repeated field default value not empty list: %s' % ( + field.default_value)) + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + # We can't look at _concrete_class yet since it might not have + # been set. (Depends on order in which we initialize the classes). + message_type = field.message_type + def MakeRepeatedMessageDefault(message): + return containers.RepeatedCompositeFieldContainer( + message._listener_for_children, field.message_type) + return MakeRepeatedMessageDefault + else: + type_checker = type_checkers.GetTypeChecker(field) + def MakeRepeatedScalarDefault(message): + return containers.RepeatedScalarFieldContainer( + message._listener_for_children, type_checker) + return MakeRepeatedScalarDefault + + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + # _concrete_class may not yet be initialized. + message_type = field.message_type + def MakeSubMessageDefault(message): + result = message_type._concrete_class() + result._SetListener(message._listener_for_children) + return result + return MakeSubMessageDefault + + def MakeScalarDefault(message): + # TODO(protobuf-team): This may be broken since there may not be + # default_value. Combine with has_default_value somehow. + return field.default_value + return MakeScalarDefault + + +def _AddInitMethod(message_descriptor, cls): + """Adds an __init__ method to cls.""" + fields = message_descriptor.fields + def init(self, **kwargs): + self._cached_byte_size = 0 + self._cached_byte_size_dirty = len(kwargs) > 0 + self._fields = {} + # Contains a mapping from oneof field descriptors to the descriptor + # of the currently set field in that oneof field. + self._oneofs = {} + + # _unknown_fields is () when empty for efficiency, and will be turned into + # a list if fields are added. + self._unknown_fields = () + self._is_present_in_parent = False + self._listener = message_listener_mod.NullMessageListener() + self._listener_for_children = _Listener(self) + for field_name, field_value in kwargs.iteritems(): + field = _GetFieldByName(message_descriptor, field_name) + if field is None: + raise TypeError("%s() got an unexpected keyword argument '%s'" % + (message_descriptor.name, field_name)) + if field.label == _FieldDescriptor.LABEL_REPEATED: + copy = field._default_constructor(self) + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite + for val in field_value: + copy.add().MergeFrom(val) + else: # Scalar + copy.extend(field_value) + self._fields[field] = copy + elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + copy = field._default_constructor(self) + copy.MergeFrom(field_value) + self._fields[field] = copy + else: + setattr(self, field_name, field_value) + + init.__module__ = None + init.__doc__ = None + cls.__init__ = init + + +def _GetFieldByName(message_descriptor, field_name): + """Returns a field descriptor by field name. + + Args: + message_descriptor: A Descriptor describing all fields in message. + field_name: The name of the field to retrieve. + Returns: + The field descriptor associated with the field name. + """ + try: + return message_descriptor.fields_by_name[field_name] + except KeyError: + raise ValueError('Protocol message has no "%s" field.' % field_name) + + +def _AddPropertiesForFields(descriptor, cls): + """Adds properties for all fields in this protocol message type.""" + for field in descriptor.fields: + _AddPropertiesForField(field, cls) + + if descriptor.is_extendable: + # _ExtensionDict is just an adaptor with no state so we allocate a new one + # every time it is accessed. + cls.Extensions = property(lambda self: _ExtensionDict(self)) + + +def _AddPropertiesForField(field, cls): + """Adds a public property for a protocol message field. + Clients can use this property to get and (in the case + of non-repeated scalar fields) directly set the value + of a protocol message field. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + # Catch it if we add other types that we should + # handle specially here. + assert _FieldDescriptor.MAX_CPPTYPE == 10 + + constant_name = field.name.upper() + "_FIELD_NUMBER" + setattr(cls, constant_name, field.number) + + if field.label == _FieldDescriptor.LABEL_REPEATED: + _AddPropertiesForRepeatedField(field, cls) + elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + _AddPropertiesForNonRepeatedCompositeField(field, cls) + else: + _AddPropertiesForNonRepeatedScalarField(field, cls) + + +def _AddPropertiesForRepeatedField(field, cls): + """Adds a public property for a "repeated" protocol message field. Clients + can use this property to get the value of the field, which will be either a + _RepeatedScalarFieldContainer or _RepeatedCompositeFieldContainer (see + below). + + Note that when clients add values to these containers, we perform + type-checking in the case of repeated scalar fields, and we also set any + necessary "has" bits as a side-effect. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + proto_field_name = field.name + property_name = _PropertyName(proto_field_name) + + def getter(self): + field_value = self._fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + + # Atomically check if another thread has preempted us and, if not, swap + # in the new object we just created. If someone has preempted us, we + # take that object and discard ours. + # WARNING: We are relying on setdefault() being atomic. This is true + # in CPython but we haven't investigated others. This warning appears + # in several other locations in this file. + field_value = self._fields.setdefault(field, field_value) + return field_value + getter.__module__ = None + getter.__doc__ = 'Getter for %s.' % proto_field_name + + # We define a setter just so we can throw an exception with a more + # helpful error message. + def setter(self, new_value): + raise AttributeError('Assignment not allowed to repeated field ' + '"%s" in protocol message object.' % proto_field_name) + + doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name + setattr(cls, property_name, property(getter, setter, doc=doc)) + + +def _AddPropertiesForNonRepeatedScalarField(field, cls): + """Adds a public property for a nonrepeated, scalar protocol message field. + Clients can use this property to get and directly set the value of the field. + Note that when the client sets the value of a field by using this property, + all necessary "has" bits are set as a side-effect, and we also perform + type-checking. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + proto_field_name = field.name + property_name = _PropertyName(proto_field_name) + type_checker = type_checkers.GetTypeChecker(field) + default_value = field.default_value + valid_values = set() + + def getter(self): + # TODO(protobuf-team): This may be broken since there may not be + # default_value. Combine with has_default_value somehow. + return self._fields.get(field, default_value) + getter.__module__ = None + getter.__doc__ = 'Getter for %s.' % proto_field_name + def field_setter(self, new_value): + # pylint: disable=protected-access + self._fields[field] = type_checker.CheckValue(new_value) + # Check _cached_byte_size_dirty inline to improve performance, since scalar + # setters are called frequently. + if not self._cached_byte_size_dirty: + self._Modified() + + if field.containing_oneof is not None: + def setter(self, new_value): + field_setter(self, new_value) + self._UpdateOneofState(field) + else: + setter = field_setter + + setter.__module__ = None + setter.__doc__ = 'Setter for %s.' % proto_field_name + + # Add a property to encapsulate the getter/setter. + doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name + setattr(cls, property_name, property(getter, setter, doc=doc)) + + +def _AddPropertiesForNonRepeatedCompositeField(field, cls): + """Adds a public property for a nonrepeated, composite protocol message field. + A composite field is a "group" or "message" field. + + Clients can use this property to get the value of the field, but cannot + assign to the property directly. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + # TODO(robinson): Remove duplication with similar method + # for non-repeated scalars. + proto_field_name = field.name + property_name = _PropertyName(proto_field_name) + + # TODO(komarek): Can anyone explain to me why we cache the message_type this + # way, instead of referring to field.message_type inside of getter(self)? + # What if someone sets message_type later on (which makes for simpler + # dyanmic proto descriptor and class creation code). + message_type = field.message_type + + def getter(self): + field_value = self._fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = message_type._concrete_class() # use field.message_type? + field_value._SetListener( + _OneofListener(self, field) + if field.containing_oneof is not None + else self._listener_for_children) + + # Atomically check if another thread has preempted us and, if not, swap + # in the new object we just created. If someone has preempted us, we + # take that object and discard ours. + # WARNING: We are relying on setdefault() being atomic. This is true + # in CPython but we haven't investigated others. This warning appears + # in several other locations in this file. + field_value = self._fields.setdefault(field, field_value) + return field_value + getter.__module__ = None + getter.__doc__ = 'Getter for %s.' % proto_field_name + + # We define a setter just so we can throw an exception with a more + # helpful error message. + def setter(self, new_value): + raise AttributeError('Assignment not allowed to composite field ' + '"%s" in protocol message object.' % proto_field_name) + + # Add a property to encapsulate the getter. + doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name + setattr(cls, property_name, property(getter, setter, doc=doc)) + + +def _AddPropertiesForExtensions(descriptor, cls): + """Adds properties for all fields in this protocol message type.""" + extension_dict = descriptor.extensions_by_name + for extension_name, extension_field in extension_dict.iteritems(): + constant_name = extension_name.upper() + "_FIELD_NUMBER" + setattr(cls, constant_name, extension_field.number) + + +def _AddStaticMethods(cls): + # TODO(robinson): This probably needs to be thread-safe(?) + def RegisterExtension(extension_handle): + extension_handle.containing_type = cls.DESCRIPTOR + _AttachFieldHelpers(cls, extension_handle) + + # Try to insert our extension, failing if an extension with the same number + # already exists. + actual_handle = cls._extensions_by_number.setdefault( + extension_handle.number, extension_handle) + if actual_handle is not extension_handle: + raise AssertionError( + 'Extensions "%s" and "%s" both try to extend message type "%s" with ' + 'field number %d.' % + (extension_handle.full_name, actual_handle.full_name, + cls.DESCRIPTOR.full_name, extension_handle.number)) + + cls._extensions_by_name[extension_handle.full_name] = extension_handle + + handle = extension_handle # avoid line wrapping + if _IsMessageSetExtension(handle): + # MessageSet extension. Also register under type name. + cls._extensions_by_name[ + extension_handle.message_type.full_name] = extension_handle + + cls.RegisterExtension = staticmethod(RegisterExtension) + + def FromString(s): + message = cls() + message.MergeFromString(s) + return message + cls.FromString = staticmethod(FromString) + + +def _IsPresent(item): + """Given a (FieldDescriptor, value) tuple from _fields, return true if the + value should be included in the list returned by ListFields().""" + + if item[0].label == _FieldDescriptor.LABEL_REPEATED: + return bool(item[1]) + elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + return item[1]._is_present_in_parent + else: + return True + + +def _AddListFieldsMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def ListFields(self): + all_fields = [item for item in self._fields.iteritems() if _IsPresent(item)] + all_fields.sort(key = lambda item: item[0].number) + return all_fields + + cls.ListFields = ListFields + + +def _AddHasFieldMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + singular_fields = {} + for field in message_descriptor.fields: + if field.label != _FieldDescriptor.LABEL_REPEATED: + singular_fields[field.name] = field + # Fields inside oneofs are never repeated (enforced by the compiler). + for field in message_descriptor.oneofs: + singular_fields[field.name] = field + + def HasField(self, field_name): + try: + field = singular_fields[field_name] + except KeyError: + raise ValueError( + 'Protocol message has no singular "%s" field.' % field_name) + + if isinstance(field, descriptor_mod.OneofDescriptor): + try: + return HasField(self, self._oneofs[field].name) + except KeyError: + return False + else: + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + value = self._fields.get(field) + return value is not None and value._is_present_in_parent + else: + return field in self._fields + + cls.HasField = HasField + + +def _AddClearFieldMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def ClearField(self, field_name): + try: + field = message_descriptor.fields_by_name[field_name] + except KeyError: + try: + field = message_descriptor.oneofs_by_name[field_name] + if field in self._oneofs: + field = self._oneofs[field] + else: + return + except KeyError: + raise ValueError('Protocol message has no "%s" field.' % field_name) + + if field in self._fields: + # Note: If the field is a sub-message, its listener will still point + # at us. That's fine, because the worst than can happen is that it + # will call _Modified() and invalidate our byte size. Big deal. + del self._fields[field] + + if self._oneofs.get(field.containing_oneof, None) is field: + del self._oneofs[field.containing_oneof] + + # Always call _Modified() -- even if nothing was changed, this is + # a mutating method, and thus calling it should cause the field to become + # present in the parent message. + self._Modified() + + cls.ClearField = ClearField + + +def _AddClearExtensionMethod(cls): + """Helper for _AddMessageMethods().""" + def ClearExtension(self, extension_handle): + _VerifyExtensionHandle(self, extension_handle) + + # Similar to ClearField(), above. + if extension_handle in self._fields: + del self._fields[extension_handle] + self._Modified() + cls.ClearExtension = ClearExtension + + +def _AddClearMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def Clear(self): + # Clear fields. + self._fields = {} + self._unknown_fields = () + self._Modified() + cls.Clear = Clear + + +def _AddHasExtensionMethod(cls): + """Helper for _AddMessageMethods().""" + def HasExtension(self, extension_handle): + _VerifyExtensionHandle(self, extension_handle) + if extension_handle.label == _FieldDescriptor.LABEL_REPEATED: + raise KeyError('"%s" is repeated.' % extension_handle.full_name) + + if extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + value = self._fields.get(extension_handle) + return value is not None and value._is_present_in_parent + else: + return extension_handle in self._fields + cls.HasExtension = HasExtension + + +def _AddEqualsMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def __eq__(self, other): + if (not isinstance(other, message_mod.Message) or + other.DESCRIPTOR != self.DESCRIPTOR): + return False + + if self is other: + return True + + if not self.ListFields() == other.ListFields(): + return False + + # Sort unknown fields because their order shouldn't affect equality test. + unknown_fields = list(self._unknown_fields) + unknown_fields.sort() + other_unknown_fields = list(other._unknown_fields) + other_unknown_fields.sort() + + return unknown_fields == other_unknown_fields + + cls.__eq__ = __eq__ + + +def _AddStrMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def __str__(self): + return text_format.MessageToString(self) + cls.__str__ = __str__ + + +def _AddUnicodeMethod(unused_message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def __unicode__(self): + return text_format.MessageToString(self, as_utf8=True).decode('utf-8') + cls.__unicode__ = __unicode__ + + +def _AddSetListenerMethod(cls): + """Helper for _AddMessageMethods().""" + def SetListener(self, listener): + if listener is None: + self._listener = message_listener_mod.NullMessageListener() + else: + self._listener = listener + cls._SetListener = SetListener + + +def _BytesForNonRepeatedElement(value, field_number, field_type): + """Returns the number of bytes needed to serialize a non-repeated element. + The returned byte count includes space for tag information and any + other additional space associated with serializing value. + + Args: + value: Value we're serializing. + field_number: Field number of this value. (Since the field number + is stored as part of a varint-encoded tag, this has an impact + on the total bytes required to serialize the value). + field_type: The type of the field. One of the TYPE_* constants + within FieldDescriptor. + """ + try: + fn = type_checkers.TYPE_TO_BYTE_SIZE_FN[field_type] + return fn(field_number, value) + except KeyError: + raise message_mod.EncodeError('Unrecognized field type: %d' % field_type) + + +def _AddByteSizeMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def ByteSize(self): + if not self._cached_byte_size_dirty: + return self._cached_byte_size + + size = 0 + for field_descriptor, field_value in self.ListFields(): + size += field_descriptor._sizer(field_value) + + for tag_bytes, value_bytes in self._unknown_fields: + size += len(tag_bytes) + len(value_bytes) + + self._cached_byte_size = size + self._cached_byte_size_dirty = False + self._listener_for_children.dirty = False + return size + + cls.ByteSize = ByteSize + + +def _AddSerializeToStringMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def SerializeToString(self): + # Check if the message has all of its required fields set. + errors = [] + if not self.IsInitialized(): + raise message_mod.EncodeError( + 'Message %s is missing required fields: %s' % ( + self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors()))) + return self.SerializePartialToString() + cls.SerializeToString = SerializeToString + + +def _AddSerializePartialToStringMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def SerializePartialToString(self): + out = BytesIO() + self._InternalSerialize(out.write) + return out.getvalue() + cls.SerializePartialToString = SerializePartialToString + + def InternalSerialize(self, write_bytes): + for field_descriptor, field_value in self.ListFields(): + field_descriptor._encoder(write_bytes, field_value) + for tag_bytes, value_bytes in self._unknown_fields: + write_bytes(tag_bytes) + write_bytes(value_bytes) + cls._InternalSerialize = InternalSerialize + + +def _AddMergeFromStringMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def MergeFromString(self, serialized): + length = len(serialized) + try: + if self._InternalParse(serialized, 0, length) != length: + # The only reason _InternalParse would return early is if it + # encountered an end-group tag. + raise message_mod.DecodeError('Unexpected end-group tag.') + except (IndexError, TypeError): + # Now ord(buf[p:p+1]) == ord('') gets TypeError. + raise message_mod.DecodeError('Truncated message.') + except struct.error, e: + raise message_mod.DecodeError(e) + return length # Return this for legacy reasons. + cls.MergeFromString = MergeFromString + + local_ReadTag = decoder.ReadTag + local_SkipField = decoder.SkipField + decoders_by_tag = cls._decoders_by_tag + + def InternalParse(self, buffer, pos, end): + self._Modified() + field_dict = self._fields + unknown_field_list = self._unknown_fields + while pos != end: + (tag_bytes, new_pos) = local_ReadTag(buffer, pos) + field_decoder = decoders_by_tag.get(tag_bytes) + if field_decoder is None: + value_start_pos = new_pos + new_pos = local_SkipField(buffer, new_pos, end, tag_bytes) + if new_pos == -1: + return pos + if not unknown_field_list: + unknown_field_list = self._unknown_fields = [] + unknown_field_list.append((tag_bytes, buffer[value_start_pos:new_pos])) + pos = new_pos + else: + pos = field_decoder(buffer, new_pos, end, self, field_dict) + return pos + cls._InternalParse = InternalParse + + +def _AddIsInitializedMethod(message_descriptor, cls): + """Adds the IsInitialized and FindInitializationError methods to the + protocol message class.""" + + required_fields = [field for field in message_descriptor.fields + if field.label == _FieldDescriptor.LABEL_REQUIRED] + + def IsInitialized(self, errors=None): + """Checks if all required fields of a message are set. + + Args: + errors: A list which, if provided, will be populated with the field + paths of all missing required fields. + + Returns: + True iff the specified message has all required fields set. + """ + + # Performance is critical so we avoid HasField() and ListFields(). + + for field in required_fields: + if (field not in self._fields or + (field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and + not self._fields[field]._is_present_in_parent)): + if errors is not None: + errors.extend(self.FindInitializationErrors()) + return False + + for field, value in list(self._fields.items()): # dict can change size! + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + if field.label == _FieldDescriptor.LABEL_REPEATED: + for element in value: + if not element.IsInitialized(): + if errors is not None: + errors.extend(self.FindInitializationErrors()) + return False + elif value._is_present_in_parent and not value.IsInitialized(): + if errors is not None: + errors.extend(self.FindInitializationErrors()) + return False + + return True + + cls.IsInitialized = IsInitialized + + def FindInitializationErrors(self): + """Finds required fields which are not initialized. + + Returns: + A list of strings. Each string is a path to an uninitialized field from + the top-level message, e.g. "foo.bar[5].baz". + """ + + errors = [] # simplify things + + for field in required_fields: + if not self.HasField(field.name): + errors.append(field.name) + + for field, value in self.ListFields(): + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + if field.is_extension: + name = "(%s)" % field.full_name + else: + name = field.name + + if field.label == _FieldDescriptor.LABEL_REPEATED: + for i in xrange(len(value)): + element = value[i] + prefix = "%s[%d]." % (name, i) + sub_errors = element.FindInitializationErrors() + errors += [ prefix + error for error in sub_errors ] + else: + prefix = name + "." + sub_errors = value.FindInitializationErrors() + errors += [ prefix + error for error in sub_errors ] + + return errors + + cls.FindInitializationErrors = FindInitializationErrors + + +def _AddMergeFromMethod(cls): + LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED + CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE + + def MergeFrom(self, msg): + if not isinstance(msg, cls): + raise TypeError( + "Parameter to MergeFrom() must be instance of same class: " + "expected %s got %s." % (cls.__name__, type(msg).__name__)) + + assert msg is not self + self._Modified() + + fields = self._fields + + for field, value in msg._fields.iteritems(): + if field.label == LABEL_REPEATED: + field_value = fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + fields[field] = field_value + field_value.MergeFrom(value) + elif field.cpp_type == CPPTYPE_MESSAGE: + if value._is_present_in_parent: + field_value = fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + fields[field] = field_value + field_value.MergeFrom(value) + else: + self._fields[field] = value + + if msg._unknown_fields: + if not self._unknown_fields: + self._unknown_fields = [] + self._unknown_fields.extend(msg._unknown_fields) + + cls.MergeFrom = MergeFrom + + +def _AddWhichOneofMethod(message_descriptor, cls): + def WhichOneof(self, oneof_name): + """Returns the name of the currently set field inside a oneof, or None.""" + try: + field = message_descriptor.oneofs_by_name[oneof_name] + except KeyError: + raise ValueError( + 'Protocol message has no oneof "%s" field.' % oneof_name) + + nested_field = self._oneofs.get(field, None) + if nested_field is not None and self.HasField(nested_field.name): + return nested_field.name + else: + return None + + cls.WhichOneof = WhichOneof + + +def _AddMessageMethods(message_descriptor, cls): + """Adds implementations of all Message methods to cls.""" + _AddListFieldsMethod(message_descriptor, cls) + _AddHasFieldMethod(message_descriptor, cls) + _AddClearFieldMethod(message_descriptor, cls) + if message_descriptor.is_extendable: + _AddClearExtensionMethod(cls) + _AddHasExtensionMethod(cls) + _AddClearMethod(message_descriptor, cls) + _AddEqualsMethod(message_descriptor, cls) + _AddStrMethod(message_descriptor, cls) + _AddUnicodeMethod(message_descriptor, cls) + _AddSetListenerMethod(cls) + _AddByteSizeMethod(message_descriptor, cls) + _AddSerializeToStringMethod(message_descriptor, cls) + _AddSerializePartialToStringMethod(message_descriptor, cls) + _AddMergeFromStringMethod(message_descriptor, cls) + _AddIsInitializedMethod(message_descriptor, cls) + _AddMergeFromMethod(cls) + _AddWhichOneofMethod(message_descriptor, cls) + +def _AddPrivateHelperMethods(message_descriptor, cls): + """Adds implementation of private helper methods to cls.""" + + def Modified(self): + """Sets the _cached_byte_size_dirty bit to true, + and propagates this to our listener iff this was a state change. + """ + + # Note: Some callers check _cached_byte_size_dirty before calling + # _Modified() as an extra optimization. So, if this method is ever + # changed such that it does stuff even when _cached_byte_size_dirty is + # already true, the callers need to be updated. + if not self._cached_byte_size_dirty: + self._cached_byte_size_dirty = True + self._listener_for_children.dirty = True + self._is_present_in_parent = True + self._listener.Modified() + + def _UpdateOneofState(self, field): + """Sets field as the active field in its containing oneof. + + Will also delete currently active field in the oneof, if it is different + from the argument. Does not mark the message as modified. + """ + other_field = self._oneofs.setdefault(field.containing_oneof, field) + if other_field is not field: + del self._fields[other_field] + self._oneofs[field.containing_oneof] = field + + cls._Modified = Modified + cls.SetInParent = Modified + cls._UpdateOneofState = _UpdateOneofState + + +class _Listener(object): + + """MessageListener implementation that a parent message registers with its + child message. + + In order to support semantics like: + + foo.bar.baz.qux = 23 + assert foo.HasField('bar') + + ...child objects must have back references to their parents. + This helper class is at the heart of this support. + """ + + def __init__(self, parent_message): + """Args: + parent_message: The message whose _Modified() method we should call when + we receive Modified() messages. + """ + # This listener establishes a back reference from a child (contained) object + # to its parent (containing) object. We make this a weak reference to avoid + # creating cyclic garbage when the client finishes with the 'parent' object + # in the tree. + if isinstance(parent_message, weakref.ProxyType): + self._parent_message_weakref = parent_message + else: + self._parent_message_weakref = weakref.proxy(parent_message) + + # As an optimization, we also indicate directly on the listener whether + # or not the parent message is dirty. This way we can avoid traversing + # up the tree in the common case. + self.dirty = False + + def Modified(self): + if self.dirty: + return + try: + # Propagate the signal to our parents iff this is the first field set. + self._parent_message_weakref._Modified() + except ReferenceError: + # We can get here if a client has kept a reference to a child object, + # and is now setting a field on it, but the child's parent has been + # garbage-collected. This is not an error. + pass + + +class _OneofListener(_Listener): + """Special listener implementation for setting composite oneof fields.""" + + def __init__(self, parent_message, field): + """Args: + parent_message: The message whose _Modified() method we should call when + we receive Modified() messages. + field: The descriptor of the field being set in the parent message. + """ + super(_OneofListener, self).__init__(parent_message) + self._field = field + + def Modified(self): + """Also updates the state of the containing oneof in the parent message.""" + try: + self._parent_message_weakref._UpdateOneofState(self._field) + super(_OneofListener, self).Modified() + except ReferenceError: + pass + + +# TODO(robinson): Move elsewhere? This file is getting pretty ridiculous... +# TODO(robinson): Unify error handling of "unknown extension" crap. +# TODO(robinson): Support iteritems()-style iteration over all +# extensions with the "has" bits turned on? +class _ExtensionDict(object): + + """Dict-like container for supporting an indexable "Extensions" + field on proto instances. + + Note that in all cases we expect extension handles to be + FieldDescriptors. + """ + + def __init__(self, extended_message): + """extended_message: Message instance for which we are the Extensions dict. + """ + + self._extended_message = extended_message + + def __getitem__(self, extension_handle): + """Returns the current value of the given extension handle.""" + + _VerifyExtensionHandle(self._extended_message, extension_handle) + + result = self._extended_message._fields.get(extension_handle) + if result is not None: + return result + + if extension_handle.label == _FieldDescriptor.LABEL_REPEATED: + result = extension_handle._default_constructor(self._extended_message) + elif extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + result = extension_handle.message_type._concrete_class() + try: + result._SetListener(self._extended_message._listener_for_children) + except ReferenceError: + pass + else: + # Singular scalar -- just return the default without inserting into the + # dict. + return extension_handle.default_value + + # Atomically check if another thread has preempted us and, if not, swap + # in the new object we just created. If someone has preempted us, we + # take that object and discard ours. + # WARNING: We are relying on setdefault() being atomic. This is true + # in CPython but we haven't investigated others. This warning appears + # in several other locations in this file. + result = self._extended_message._fields.setdefault( + extension_handle, result) + + return result + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return False + + my_fields = self._extended_message.ListFields() + other_fields = other._extended_message.ListFields() + + # Get rid of non-extension fields. + my_fields = [ field for field in my_fields if field.is_extension ] + other_fields = [ field for field in other_fields if field.is_extension ] + + return my_fields == other_fields + + def __ne__(self, other): + return not self == other + + def __hash__(self): + raise TypeError('unhashable object') + + # Note that this is only meaningful for non-repeated, scalar extension + # fields. Note also that we may have to call _Modified() when we do + # successfully set a field this way, to set any necssary "has" bits in the + # ancestors of the extended message. + def __setitem__(self, extension_handle, value): + """If extension_handle specifies a non-repeated, scalar extension + field, sets the value of that field. + """ + + _VerifyExtensionHandle(self._extended_message, extension_handle) + + if (extension_handle.label == _FieldDescriptor.LABEL_REPEATED or + extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE): + raise TypeError( + 'Cannot assign to extension "%s" because it is a repeated or ' + 'composite type.' % extension_handle.full_name) + + # It's slightly wasteful to lookup the type checker each time, + # but we expect this to be a vanishingly uncommon case anyway. + type_checker = type_checkers.GetTypeChecker( + extension_handle) + # pylint: disable=protected-access + self._extended_message._fields[extension_handle] = ( + type_checker.CheckValue(value)) + self._extended_message._Modified() + + def _FindExtensionByName(self, name): + """Tries to find a known extension with the specified name. + + Args: + name: Extension full name. + + Returns: + Extension field descriptor. + """ + return self._extended_message._extensions_by_name.get(name, None) diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py index 2c9fa30..b3c414c 100755 --- a/python/google/protobuf/internal/reflection_test.py +++ b/python/google/protobuf/internal/reflection_test.py @@ -37,12 +37,12 @@ pure-Python protocol compiler. __author__ = 'robinson@google.com (Will Robinson)' +import copy +import gc import operator import struct -import unittest -# TODO(robinson): When we split this test in two, only some of these imports -# will be necessary in each test. +from google.apputils import basetest from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_mset_pb2 from google.protobuf import unittest_pb2 @@ -50,6 +50,8 @@ from google.protobuf import descriptor_pb2 from google.protobuf import descriptor from google.protobuf import message from google.protobuf import reflection +from google.protobuf import text_format +from google.protobuf.internal import api_implementation from google.protobuf.internal import more_extensions_pb2 from google.protobuf.internal import more_messages_pb2 from google.protobuf.internal import wire_format @@ -102,12 +104,12 @@ class _MiniDecoder(object): return self._pos == len(self._bytes) -class ReflectionTest(unittest.TestCase): +class ReflectionTest(basetest.TestCase): - def assertIs(self, values, others): + def assertListsEqual(self, values, others): self.assertEqual(len(values), len(others)) for i in range(len(values)): - self.assertTrue(values[i] is others[i]) + self.assertEqual(values[i], others[i]) def testScalarConstructor(self): # Constructor with only scalar types should succeed. @@ -200,6 +202,41 @@ class ReflectionTest(unittest.TestCase): unittest_pb2.ForeignMessage(c=12)], list(proto.repeated_foreign_message)) + def testConstructorTypeError(self): + self.assertRaises( + TypeError, unittest_pb2.TestAllTypes, optional_int32="foo") + self.assertRaises( + TypeError, unittest_pb2.TestAllTypes, optional_string=1234) + self.assertRaises( + TypeError, unittest_pb2.TestAllTypes, optional_nested_message=1234) + self.assertRaises( + TypeError, unittest_pb2.TestAllTypes, repeated_int32=1234) + self.assertRaises( + TypeError, unittest_pb2.TestAllTypes, repeated_int32=["foo"]) + self.assertRaises( + TypeError, unittest_pb2.TestAllTypes, repeated_string=1234) + self.assertRaises( + TypeError, unittest_pb2.TestAllTypes, repeated_string=[1234]) + self.assertRaises( + TypeError, unittest_pb2.TestAllTypes, repeated_nested_message=1234) + self.assertRaises( + TypeError, unittest_pb2.TestAllTypes, repeated_nested_message=[1234]) + + def testConstructorInvalidatesCachedByteSize(self): + message = unittest_pb2.TestAllTypes(optional_int32 = 12) + self.assertEquals(2, message.ByteSize()) + + message = unittest_pb2.TestAllTypes( + optional_nested_message = unittest_pb2.TestAllTypes.NestedMessage()) + self.assertEquals(3, message.ByteSize()) + + message = unittest_pb2.TestAllTypes(repeated_int32 = [12]) + self.assertEquals(3, message.ByteSize()) + + message = unittest_pb2.TestAllTypes( + repeated_nested_message = [unittest_pb2.TestAllTypes.NestedMessage()]) + self.assertEquals(3, message.ByteSize()) + def testSimpleHasBits(self): # Test a scalar. proto = unittest_pb2.TestAllTypes() @@ -284,12 +321,6 @@ class ReflectionTest(unittest.TestCase): # ...and ensure that the scalar field has returned to its default. self.assertEqual(0, getattr(composite_field, scalar_field_name)) - # Finally, ensure that modifications to the old composite field object - # don't have any effect on the parent. - # - # (NOTE that when we clear the composite field in the parent, we actually - # don't recursively clear down the tree. Instead, we just disconnect the - # cleared composite from the tree.) self.assertTrue(old_composite_field is not composite_field) setattr(old_composite_field, scalar_field_name, new_val) self.assertTrue(not composite_field.HasField(scalar_field_name)) @@ -319,6 +350,64 @@ class ReflectionTest(unittest.TestCase): self.assertTrue(not proto.HasField('optional_nested_message')) self.assertEqual(0, proto.optional_nested_message.bb) + def testGetDefaultMessageAfterDisconnectingDefaultMessage(self): + proto = unittest_pb2.TestAllTypes() + nested = proto.optional_nested_message + proto.ClearField('optional_nested_message') + del proto + del nested + # Force a garbage collect so that the underlying CMessages are freed along + # with the Messages they point to. This is to make sure we're not deleting + # default message instances. + gc.collect() + proto = unittest_pb2.TestAllTypes() + nested = proto.optional_nested_message + + def testDisconnectingNestedMessageAfterSettingField(self): + proto = unittest_pb2.TestAllTypes() + nested = proto.optional_nested_message + nested.bb = 5 + self.assertTrue(proto.HasField('optional_nested_message')) + proto.ClearField('optional_nested_message') # Should disconnect from parent + self.assertEqual(5, nested.bb) + self.assertEqual(0, proto.optional_nested_message.bb) + self.assertTrue(nested is not proto.optional_nested_message) + nested.bb = 23 + self.assertTrue(not proto.HasField('optional_nested_message')) + self.assertEqual(0, proto.optional_nested_message.bb) + + def testDisconnectingNestedMessageBeforeGettingField(self): + proto = unittest_pb2.TestAllTypes() + self.assertTrue(not proto.HasField('optional_nested_message')) + proto.ClearField('optional_nested_message') + self.assertTrue(not proto.HasField('optional_nested_message')) + + def testDisconnectingNestedMessageAfterMerge(self): + # This test exercises the code path that does not use ReleaseMessage(). + # The underlying fear is that if we use ReleaseMessage() incorrectly, + # we will have memory leaks. It's hard to check that that doesn't happen, + # but at least we can exercise that code path to make sure it works. + proto1 = unittest_pb2.TestAllTypes() + proto2 = unittest_pb2.TestAllTypes() + proto2.optional_nested_message.bb = 5 + proto1.MergeFrom(proto2) + self.assertTrue(proto1.HasField('optional_nested_message')) + proto1.ClearField('optional_nested_message') + self.assertTrue(not proto1.HasField('optional_nested_message')) + + def testDisconnectingLazyNestedMessage(self): + # This test exercises releasing a nested message that is lazy. This test + # only exercises real code in the C++ implementation as Python does not + # support lazy parsing, but the current C++ implementation results in + # memory corruption and a crash. + if api_implementation.Type() != 'python': + return + proto = unittest_pb2.TestAllTypes() + proto.optional_lazy_message.bb = 5 + proto.ClearField('optional_lazy_message') + del proto + gc.collect() + def testHasBitsWhenModifyingRepeatedFields(self): # Test nesting when we add an element to a repeated field in a submessage. proto = unittest_pb2.TestNestedMessageHasBits() @@ -446,7 +535,7 @@ class ReflectionTest(unittest.TestCase): self.assertEqual(0.0, proto.optional_double) self.assertEqual(False, proto.optional_bool) self.assertEqual('', proto.optional_string) - self.assertEqual('', proto.optional_bytes) + self.assertEqual(b'', proto.optional_bytes) self.assertEqual(41, proto.default_int32) self.assertEqual(42, proto.default_int64) @@ -462,7 +551,7 @@ class ReflectionTest(unittest.TestCase): self.assertEqual(52e3, proto.default_double) self.assertEqual(True, proto.default_bool) self.assertEqual('hello', proto.default_string) - self.assertEqual('world', proto.default_bytes) + self.assertEqual(b'world', proto.default_bytes) self.assertEqual(unittest_pb2.TestAllTypes.BAR, proto.default_nested_enum) self.assertEqual(unittest_pb2.FOREIGN_BAR, proto.default_foreign_enum) self.assertEqual(unittest_import_pb2.IMPORT_BAR, @@ -479,6 +568,17 @@ class ReflectionTest(unittest.TestCase): proto = unittest_pb2.TestAllTypes() self.assertRaises(ValueError, proto.ClearField, 'nonexistent_field') + def testClearRemovesChildren(self): + # Make sure there aren't any implementation bugs that are only partially + # clearing the message (which can happen in the more complex C++ + # implementation which has parallel message lists). + proto = unittest_pb2.TestRequiredForeign() + for i in range(10): + proto.repeated_message.add() + proto2 = unittest_pb2.TestRequiredForeign() + proto.CopyFrom(proto2) + self.assertRaises(IndexError, lambda: proto.repeated_message[5]) + def testDisallowedAssignments(self): # It's illegal to assign values directly to repeated fields # or to nonrepeated composite fields. Ensure that this fails. @@ -500,7 +600,6 @@ class ReflectionTest(unittest.TestCase): # proto.nonexistent_field = 23 should fail as well. self.assertRaises(AttributeError, setattr, proto, 'nonexistent_field', 23) - # TODO(robinson): Add type-safety check for enums. def testSingleScalarTypeSafety(self): proto = unittest_pb2.TestAllTypes() self.assertRaises(TypeError, setattr, proto, 'optional_int32', 1.1) @@ -508,11 +607,37 @@ class ReflectionTest(unittest.TestCase): self.assertRaises(TypeError, setattr, proto, 'optional_string', 10) self.assertRaises(TypeError, setattr, proto, 'optional_bytes', 10) + def testIntegerTypes(self): + def TestGetAndDeserialize(field_name, value, expected_type): + proto = unittest_pb2.TestAllTypes() + setattr(proto, field_name, value) + self.assertTrue(isinstance(getattr(proto, field_name), expected_type)) + proto2 = unittest_pb2.TestAllTypes() + proto2.ParseFromString(proto.SerializeToString()) + self.assertTrue(isinstance(getattr(proto2, field_name), expected_type)) + + TestGetAndDeserialize('optional_int32', 1, int) + TestGetAndDeserialize('optional_int32', 1 << 30, int) + TestGetAndDeserialize('optional_uint32', 1 << 30, int) + 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) + else: + # 64-bit python can fit uint32 inside an int + TestGetAndDeserialize('optional_uint32', 1 << 31, int) + TestGetAndDeserialize('optional_int64', 1 << 30, long) + TestGetAndDeserialize('optional_int64', 1 << 60, long) + TestGetAndDeserialize('optional_uint64', 1 << 30, long) + TestGetAndDeserialize('optional_uint64', 1 << 60, long) + def testSingleScalarBoundsChecking(self): def TestMinAndMaxIntegers(field_name, expected_min, expected_max): pb = unittest_pb2.TestAllTypes() setattr(pb, field_name, expected_min) + self.assertEqual(expected_min, getattr(pb, field_name)) setattr(pb, field_name, expected_max) + self.assertEqual(expected_max, getattr(pb, field_name)) self.assertRaises(ValueError, setattr, pb, field_name, expected_min - 1) self.assertRaises(ValueError, setattr, pb, field_name, expected_max + 1) @@ -520,7 +645,10 @@ class ReflectionTest(unittest.TestCase): TestMinAndMaxIntegers('optional_uint32', 0, 0xffffffff) TestMinAndMaxIntegers('optional_int64', -(1 << 63), (1 << 63) - 1) TestMinAndMaxIntegers('optional_uint64', 0, 0xffffffffffffffff) - TestMinAndMaxIntegers('optional_nested_enum', -(1 << 31), (1 << 31) - 1) + + pb = unittest_pb2.TestAllTypes() + pb.optional_nested_enum = 1 + self.assertEqual(1, pb.optional_nested_enum) def testRepeatedScalarTypeSafety(self): proto = unittest_pb2.TestAllTypes() @@ -534,11 +662,19 @@ class ReflectionTest(unittest.TestCase): self.assertRaises(IndexError, proto.repeated_int32.__setitem__, 500, 23) self.assertRaises(TypeError, proto.repeated_int32.__setitem__, 0, 'abc') + # Repeated enums tests. + #proto.repeated_nested_enum.append(0) + def testSingleScalarGettersAndSetters(self): proto = unittest_pb2.TestAllTypes() self.assertEqual(0, proto.optional_int32) proto.optional_int32 = 1 self.assertEqual(1, proto.optional_int32) + + proto.optional_uint64 = 0xffffffffffff + self.assertEqual(0xffffffffffff, proto.optional_uint64) + proto.optional_uint64 = 0xffffffffffffffff + self.assertEqual(0xffffffffffffffff, proto.optional_uint64) # TODO(robinson): Test all other scalar field types. def testSingleScalarClearField(self): @@ -561,6 +697,77 @@ class ReflectionTest(unittest.TestCase): self.assertEqual(3, proto.BAZ) self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ) + def testEnum_Name(self): + self.assertEqual('FOREIGN_FOO', + unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_FOO)) + self.assertEqual('FOREIGN_BAR', + unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_BAR)) + self.assertEqual('FOREIGN_BAZ', + unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_BAZ)) + self.assertRaises(ValueError, + unittest_pb2.ForeignEnum.Name, 11312) + + proto = unittest_pb2.TestAllTypes() + self.assertEqual('FOO', + proto.NestedEnum.Name(proto.FOO)) + self.assertEqual('FOO', + unittest_pb2.TestAllTypes.NestedEnum.Name(proto.FOO)) + self.assertEqual('BAR', + proto.NestedEnum.Name(proto.BAR)) + self.assertEqual('BAR', + unittest_pb2.TestAllTypes.NestedEnum.Name(proto.BAR)) + self.assertEqual('BAZ', + proto.NestedEnum.Name(proto.BAZ)) + self.assertEqual('BAZ', + unittest_pb2.TestAllTypes.NestedEnum.Name(proto.BAZ)) + self.assertRaises(ValueError, + proto.NestedEnum.Name, 11312) + self.assertRaises(ValueError, + unittest_pb2.TestAllTypes.NestedEnum.Name, 11312) + + def testEnum_Value(self): + self.assertEqual(unittest_pb2.FOREIGN_FOO, + unittest_pb2.ForeignEnum.Value('FOREIGN_FOO')) + self.assertEqual(unittest_pb2.FOREIGN_BAR, + unittest_pb2.ForeignEnum.Value('FOREIGN_BAR')) + self.assertEqual(unittest_pb2.FOREIGN_BAZ, + unittest_pb2.ForeignEnum.Value('FOREIGN_BAZ')) + self.assertRaises(ValueError, + unittest_pb2.ForeignEnum.Value, 'FO') + + proto = unittest_pb2.TestAllTypes() + self.assertEqual(proto.FOO, + proto.NestedEnum.Value('FOO')) + self.assertEqual(proto.FOO, + unittest_pb2.TestAllTypes.NestedEnum.Value('FOO')) + self.assertEqual(proto.BAR, + proto.NestedEnum.Value('BAR')) + self.assertEqual(proto.BAR, + unittest_pb2.TestAllTypes.NestedEnum.Value('BAR')) + self.assertEqual(proto.BAZ, + proto.NestedEnum.Value('BAZ')) + self.assertEqual(proto.BAZ, + unittest_pb2.TestAllTypes.NestedEnum.Value('BAZ')) + self.assertRaises(ValueError, + proto.NestedEnum.Value, 'Foo') + self.assertRaises(ValueError, + unittest_pb2.TestAllTypes.NestedEnum.Value, 'Foo') + + def testEnum_KeysAndValues(self): + self.assertEqual(['FOREIGN_FOO', 'FOREIGN_BAR', 'FOREIGN_BAZ'], + unittest_pb2.ForeignEnum.keys()) + self.assertEqual([4, 5, 6], + unittest_pb2.ForeignEnum.values()) + self.assertEqual([('FOREIGN_FOO', 4), ('FOREIGN_BAR', 5), + ('FOREIGN_BAZ', 6)], + unittest_pb2.ForeignEnum.items()) + + proto = unittest_pb2.TestAllTypes() + self.assertEqual(['FOO', 'BAR', 'BAZ', 'NEG'], proto.NestedEnum.keys()) + self.assertEqual([1, 2, 3, -1], proto.NestedEnum.values()) + self.assertEqual([('FOO', 1), ('BAR', 2), ('BAZ', 3), ('NEG', -1)], + proto.NestedEnum.items()) + def testRepeatedScalars(self): proto = unittest_pb2.TestAllTypes() @@ -619,11 +826,38 @@ class ReflectionTest(unittest.TestCase): del proto.repeated_int32[2:] self.assertEqual([5, 35], proto.repeated_int32) + # Test extending. + proto.repeated_int32.extend([3, 13]) + self.assertEqual([5, 35, 3, 13], proto.repeated_int32) + # Test clearing. proto.ClearField('repeated_int32') self.assertTrue(not proto.repeated_int32) self.assertEqual(0, len(proto.repeated_int32)) + proto.repeated_int32.append(1) + self.assertEqual(1, proto.repeated_int32[-1]) + # Test assignment to a negative index. + proto.repeated_int32[-1] = 2 + self.assertEqual(2, proto.repeated_int32[-1]) + + # Test deletion at negative indices. + proto.repeated_int32[:] = [0, 1, 2, 3] + del proto.repeated_int32[-1] + self.assertEqual([0, 1, 2], proto.repeated_int32) + + del proto.repeated_int32[-2] + self.assertEqual([0, 2], proto.repeated_int32) + + self.assertRaises(IndexError, proto.repeated_int32.__delitem__, -3) + self.assertRaises(IndexError, proto.repeated_int32.__delitem__, 300) + + del proto.repeated_int32[-2:-1] + self.assertEqual([2], proto.repeated_int32) + + del proto.repeated_int32[100:10000] + self.assertEqual([2], proto.repeated_int32) + def testRepeatedScalarsRemove(self): proto = unittest_pb2.TestAllTypes() @@ -661,7 +895,7 @@ class ReflectionTest(unittest.TestCase): m1 = proto.repeated_nested_message.add() self.assertTrue(proto.repeated_nested_message) self.assertEqual(2, len(proto.repeated_nested_message)) - self.assertIs([m0, m1], proto.repeated_nested_message) + self.assertListsEqual([m0, m1], proto.repeated_nested_message) self.assertTrue(isinstance(m0, unittest_pb2.TestAllTypes.NestedMessage)) # Test out-of-bounds indices. @@ -680,32 +914,86 @@ class ReflectionTest(unittest.TestCase): m2 = proto.repeated_nested_message.add() m3 = proto.repeated_nested_message.add() m4 = proto.repeated_nested_message.add() - self.assertIs([m1, m2, m3], proto.repeated_nested_message[1:4]) - self.assertIs([m0, m1, m2, m3, m4], proto.repeated_nested_message[:]) + self.assertListsEqual( + [m1, m2, m3], proto.repeated_nested_message[1:4]) + self.assertListsEqual( + [m0, m1, m2, m3, m4], proto.repeated_nested_message[:]) + self.assertListsEqual( + [m0, m1], proto.repeated_nested_message[:2]) + self.assertListsEqual( + [m2, m3, m4], proto.repeated_nested_message[2:]) + self.assertEqual( + m0, proto.repeated_nested_message[0]) + self.assertListsEqual( + [m0], proto.repeated_nested_message[:1]) # Test that we can use the field as an iterator. result = [] for i in proto.repeated_nested_message: result.append(i) - self.assertIs([m0, m1, m2, m3, m4], result) + self.assertListsEqual([m0, m1, m2, m3, m4], result) # Test single deletion. del proto.repeated_nested_message[2] - self.assertIs([m0, m1, m3, m4], proto.repeated_nested_message) + self.assertListsEqual([m0, m1, m3, m4], proto.repeated_nested_message) # Test slice deletion. del proto.repeated_nested_message[2:] - self.assertIs([m0, m1], proto.repeated_nested_message) + self.assertListsEqual([m0, m1], proto.repeated_nested_message) + + # Test extending. + n1 = unittest_pb2.TestAllTypes.NestedMessage(bb=1) + n2 = unittest_pb2.TestAllTypes.NestedMessage(bb=2) + proto.repeated_nested_message.extend([n1,n2]) + self.assertEqual(4, len(proto.repeated_nested_message)) + self.assertEqual(n1, proto.repeated_nested_message[2]) + self.assertEqual(n2, proto.repeated_nested_message[3]) # Test clearing. proto.ClearField('repeated_nested_message') self.assertTrue(not proto.repeated_nested_message) self.assertEqual(0, len(proto.repeated_nested_message)) + # Test constructing an element while adding it. + proto.repeated_nested_message.add(bb=23) + self.assertEqual(1, len(proto.repeated_nested_message)) + self.assertEqual(23, proto.repeated_nested_message[0].bb) + + def testRepeatedCompositeRemove(self): + proto = unittest_pb2.TestAllTypes() + + self.assertEqual(0, len(proto.repeated_nested_message)) + m0 = proto.repeated_nested_message.add() + # Need to set some differentiating variable so m0 != m1 != m2: + m0.bb = len(proto.repeated_nested_message) + m1 = proto.repeated_nested_message.add() + m1.bb = len(proto.repeated_nested_message) + self.assertTrue(m0 != m1) + m2 = proto.repeated_nested_message.add() + m2.bb = len(proto.repeated_nested_message) + self.assertListsEqual([m0, m1, m2], proto.repeated_nested_message) + + self.assertEqual(3, len(proto.repeated_nested_message)) + proto.repeated_nested_message.remove(m0) + self.assertEqual(2, len(proto.repeated_nested_message)) + self.assertEqual(m1, proto.repeated_nested_message[0]) + self.assertEqual(m2, proto.repeated_nested_message[1]) + + # Removing m0 again or removing None should raise error + self.assertRaises(ValueError, proto.repeated_nested_message.remove, m0) + self.assertRaises(ValueError, proto.repeated_nested_message.remove, None) + self.assertEqual(2, len(proto.repeated_nested_message)) + + proto.repeated_nested_message.remove(m2) + self.assertEqual(1, len(proto.repeated_nested_message)) + self.assertEqual(m1, proto.repeated_nested_message[0]) + def testHandWrittenReflection(self): - # TODO(robinson): We probably need a better way to specify - # protocol types by hand. But then again, this isn't something - # we expect many people to do. Hmm. + # Hand written extensions are only supported by the pure-Python + # implementation of the API. + if api_implementation.Type() != 'python': + return + FieldDescriptor = descriptor.FieldDescriptor foo_field_descriptor = FieldDescriptor( name='foo_field', full_name='MyProto.foo_field', @@ -730,6 +1018,68 @@ class ReflectionTest(unittest.TestCase): self.assertEqual(23, myproto_instance.foo_field) self.assertTrue(myproto_instance.HasField('foo_field')) + def testDescriptorProtoSupport(self): + # Hand written descriptors/reflection are only supported by the pure-Python + # implementation of the API. + if api_implementation.Type() != 'python': + return + + def AddDescriptorField(proto, field_name, field_type): + AddDescriptorField.field_index += 1 + new_field = proto.field.add() + new_field.name = field_name + new_field.type = field_type + new_field.number = AddDescriptorField.field_index + new_field.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL + + AddDescriptorField.field_index = 0 + + desc_proto = descriptor_pb2.DescriptorProto() + desc_proto.name = 'Car' + fdp = descriptor_pb2.FieldDescriptorProto + AddDescriptorField(desc_proto, 'name', fdp.TYPE_STRING) + AddDescriptorField(desc_proto, 'year', fdp.TYPE_INT64) + AddDescriptorField(desc_proto, 'automatic', fdp.TYPE_BOOL) + AddDescriptorField(desc_proto, 'price', fdp.TYPE_DOUBLE) + # Add a repeated field + AddDescriptorField.field_index += 1 + new_field = desc_proto.field.add() + new_field.name = 'owners' + new_field.type = fdp.TYPE_STRING + new_field.number = AddDescriptorField.field_index + new_field.label = descriptor_pb2.FieldDescriptorProto.LABEL_REPEATED + + desc = descriptor.MakeDescriptor(desc_proto) + self.assertTrue(desc.fields_by_name.has_key('name')) + self.assertTrue(desc.fields_by_name.has_key('year')) + self.assertTrue(desc.fields_by_name.has_key('automatic')) + self.assertTrue(desc.fields_by_name.has_key('price')) + self.assertTrue(desc.fields_by_name.has_key('owners')) + + class CarMessage(message.Message): + __metaclass__ = reflection.GeneratedProtocolMessageType + DESCRIPTOR = desc + + prius = CarMessage() + prius.name = 'prius' + prius.year = 2010 + prius.automatic = True + prius.price = 25134.75 + prius.owners.extend(['bob', 'susan']) + + serialized_prius = prius.SerializeToString() + new_prius = reflection.ParseMessage(desc, serialized_prius) + self.assertTrue(new_prius is not prius) + self.assertEqual(prius, new_prius) + + # these are unnecessary assuming message equality works as advertised but + # explicitly check to be safe since we're mucking about in metaclass foo + self.assertEqual(prius.name, new_prius.name) + self.assertEqual(prius.year, new_prius.year) + self.assertEqual(prius.automatic, new_prius.automatic) + self.assertEqual(prius.price, new_prius.price) + self.assertEqual(prius.owners, new_prius.owners) + def testTopLevelExtensionsForOptionalScalar(self): extendee_proto = unittest_pb2.TestAllExtensions() extension = unittest_pb2.optional_int32_extension @@ -819,6 +1169,14 @@ class ReflectionTest(unittest.TestCase): self.assertTrue(required is not extendee_proto.Extensions[extension]) self.assertTrue(not extendee_proto.HasExtension(extension)) + def testRegisteredExtensions(self): + self.assertTrue('protobuf_unittest.optional_int32_extension' in + unittest_pb2.TestAllExtensions._extensions_by_name) + self.assertTrue(1 in unittest_pb2.TestAllExtensions._extensions_by_number) + # Make sure extensions haven't been registered into types that shouldn't + # have any. + self.assertEquals(0, len(unittest_pb2.TestAllTypes._extensions_by_name)) + # If message A directly contains message B, and # a.HasField('b') is currently False, then mutating any # extension in B should change a.HasField('b') to True @@ -868,7 +1226,7 @@ class ReflectionTest(unittest.TestCase): self.assertTrue(not toplevel.HasField('submessage')) foreign = toplevel.submessage.Extensions[ more_extensions_pb2.repeated_message_extension].add() - self.assertTrue(foreign is toplevel.submessage.Extensions[ + self.assertEqual(foreign, toplevel.submessage.Extensions[ more_extensions_pb2.repeated_message_extension][0]) self.assertTrue(toplevel.HasField('submessage')) @@ -971,6 +1329,12 @@ class ReflectionTest(unittest.TestCase): self.assertEqual(123, proto2.repeated_nested_message[1].bb) self.assertEqual(321, proto2.repeated_nested_message[2].bb) + proto3 = unittest_pb2.TestAllTypes() + proto3.repeated_nested_message.MergeFrom(proto2.repeated_nested_message) + self.assertEqual(999, proto3.repeated_nested_message[0].bb) + self.assertEqual(123, proto3.repeated_nested_message[1].bb) + self.assertEqual(321, proto3.repeated_nested_message[2].bb) + def testMergeFromAllFields(self): # With all fields set. proto1 = unittest_pb2.TestAllTypes() @@ -1035,6 +1399,19 @@ class ReflectionTest(unittest.TestCase): self.assertEqual(222, ext2[1].bb) self.assertEqual(333, ext2[2].bb) + def testMergeFromBug(self): + message1 = unittest_pb2.TestAllTypes() + message2 = unittest_pb2.TestAllTypes() + + # Cause optional_nested_message to be instantiated within message1, even + # though it is not considered to be "present". + message1.optional_nested_message + self.assertFalse(message1.HasField('optional_nested_message')) + + # Merge into message2. This should not instantiate the field is message2. + message2.MergeFrom(message1) + self.assertFalse(message2.HasField('optional_nested_message')) + def testCopyFromSingularField(self): # Test copy with just a singular field. proto1 = unittest_pb2.TestAllTypes() @@ -1087,9 +1464,36 @@ class ReflectionTest(unittest.TestCase): self.assertEqual(2, proto1.optional_int32) self.assertEqual('important-text', proto1.optional_string) + def testCopyFromBadType(self): + # The python implementation doesn't raise an exception in this + # case. In theory it should. + if api_implementation.Type() == 'python': + return + proto1 = unittest_pb2.TestAllTypes() + proto2 = unittest_pb2.TestAllExtensions() + self.assertRaises(TypeError, proto1.CopyFrom, proto2) + + def testDeepCopy(self): + proto1 = unittest_pb2.TestAllTypes() + proto1.optional_int32 = 1 + proto2 = copy.deepcopy(proto1) + self.assertEqual(1, proto2.optional_int32) + + proto1.repeated_int32.append(2) + proto1.repeated_int32.append(3) + container = copy.deepcopy(proto1.repeated_int32) + self.assertEqual([2, 3], container) + + # TODO(anuraag): Implement deepcopy for repeated composite / extension dict + def testClear(self): proto = unittest_pb2.TestAllTypes() - test_util.SetAllFields(proto) + # C++ implementation does not support lazy fields right now so leave it + # out for now. + if api_implementation.Type() == 'python': + test_util.SetAllFields(proto) + else: + test_util.SetAllNonLazyFields(proto) # Clear the message. proto.Clear() self.assertEquals(proto.ByteSize(), 0) @@ -1105,6 +1509,45 @@ class ReflectionTest(unittest.TestCase): empty_proto = unittest_pb2.TestAllExtensions() self.assertEquals(proto, empty_proto) + def testDisconnectingBeforeClear(self): + proto = unittest_pb2.TestAllTypes() + nested = proto.optional_nested_message + proto.Clear() + self.assertTrue(nested is not proto.optional_nested_message) + nested.bb = 23 + self.assertTrue(not proto.HasField('optional_nested_message')) + self.assertEqual(0, proto.optional_nested_message.bb) + + proto = unittest_pb2.TestAllTypes() + nested = proto.optional_nested_message + nested.bb = 5 + foreign = proto.optional_foreign_message + foreign.c = 6 + + proto.Clear() + self.assertTrue(nested is not proto.optional_nested_message) + self.assertTrue(foreign is not proto.optional_foreign_message) + self.assertEqual(5, nested.bb) + self.assertEqual(6, foreign.c) + nested.bb = 15 + foreign.c = 16 + self.assertFalse(proto.HasField('optional_nested_message')) + self.assertEqual(0, proto.optional_nested_message.bb) + self.assertFalse(proto.HasField('optional_foreign_message')) + self.assertEqual(0, proto.optional_foreign_message.c) + + def testOneOf(self): + proto = unittest_pb2.TestAllTypes() + proto.oneof_uint32 = 10 + proto.oneof_nested_message.bb = 11 + self.assertEqual(11, proto.oneof_nested_message.bb) + self.assertFalse(proto.HasField('oneof_uint32')) + nested = proto.oneof_nested_message + proto.oneof_string = 'abc' + self.assertEqual('abc', proto.oneof_string) + self.assertEqual(11, nested.bb) + self.assertFalse(proto.HasField('oneof_nested_message')) + def assertInitialized(self, proto): self.assertTrue(proto.IsInitialized()) # Neither method should raise an exception. @@ -1175,6 +1618,40 @@ class ReflectionTest(unittest.TestCase): self.assertFalse(proto.IsInitialized(errors)) self.assertEqual(errors, ['a', 'b', 'c']) + @basetest.unittest.skipIf( + api_implementation.Type() != 'cpp' or api_implementation.Version() != 2, + 'Errors are only available from the most recent C++ implementation.') + def testFileDescriptorErrors(self): + file_name = 'test_file_descriptor_errors.proto' + package_name = 'test_file_descriptor_errors.proto' + file_descriptor_proto = descriptor_pb2.FileDescriptorProto() + file_descriptor_proto.name = file_name + file_descriptor_proto.package = package_name + m1 = file_descriptor_proto.message_type.add() + m1.name = 'msg1' + # Compiles the proto into the C++ descriptor pool + descriptor.FileDescriptor( + file_name, + package_name, + serialized_pb=file_descriptor_proto.SerializeToString()) + # Add a FileDescriptorProto that has duplicate symbols + another_file_name = 'another_test_file_descriptor_errors.proto' + file_descriptor_proto.name = another_file_name + m2 = file_descriptor_proto.message_type.add() + m2.name = 'msg2' + with self.assertRaises(TypeError) as cm: + descriptor.FileDescriptor( + another_file_name, + package_name, + serialized_pb=file_descriptor_proto.SerializeToString()) + self.assertTrue(hasattr(cm, 'exception'), '%s not raised' % + getattr(cm.expected, '__name__', cm.expected)) + self.assertIn('test_file_descriptor_errors.proto', str(cm.exception)) + # Error message will say something about this definition being a + # duplicate, though we don't check the message exactly to avoid a + # dependency on the C++ logging code. + self.assertIn('test_file_descriptor_errors.msg1', str(cm.exception)) + def testStringUTF8Encoding(self): proto = unittest_pb2.TestAllTypes() @@ -1192,16 +1669,15 @@ class ReflectionTest(unittest.TestCase): proto.optional_string = str('Testing') self.assertEqual(proto.optional_string, unicode('Testing')) - # Values of type 'str' are also accepted as long as they can be encoded in - # UTF-8. - self.assertEqual(type(proto.optional_string), str) - # Try to assign a 'str' value which contains bytes that aren't 7-bit ASCII. self.assertRaises(ValueError, - setattr, proto, 'optional_string', str('a\x80a')) - # Assign a 'str' object which contains a UTF-8 encoded string. - self.assertRaises(ValueError, - setattr, proto, 'optional_string', 'Тест') + setattr, proto, 'optional_string', b'a\x80a') + if str is bytes: # PY2 + # Assign a 'str' object which contains a UTF-8 encoded string. + self.assertRaises(ValueError, + setattr, proto, 'optional_string', 'Тест') + else: + proto.optional_string = 'Тест' # No exception thrown. proto.optional_string = 'abc' @@ -1224,7 +1700,8 @@ class ReflectionTest(unittest.TestCase): self.assertEqual(proto.ByteSize(), len(serialized)) raw = unittest_mset_pb2.RawMessageSet() - raw.MergeFromString(serialized) + bytes_read = raw.MergeFromString(serialized) + self.assertEqual(len(serialized), bytes_read) message2 = unittest_mset_pb2.TestMessageSetExtension2() @@ -1232,18 +1709,37 @@ class ReflectionTest(unittest.TestCase): # Check that the type_id is the same as the tag ID in the .proto file. self.assertEqual(raw.item[0].type_id, 1547769) - # Check the actually bytes on the wire. + # Check the actual bytes on the wire. self.assertTrue( raw.item[0].message.endswith(test_utf8_bytes)) - message2.MergeFromString(raw.item[0].message) + bytes_read = message2.MergeFromString(raw.item[0].message) + self.assertEqual(len(raw.item[0].message), bytes_read) self.assertEqual(type(message2.str), unicode) self.assertEqual(message2.str, test_utf8) - # How about if the bytes on the wire aren't a valid UTF-8 encoded string. - bytes = raw.item[0].message.replace( - test_utf8_bytes, len(test_utf8_bytes) * '\xff') - self.assertRaises(UnicodeDecodeError, message2.MergeFromString, bytes) + # The pure Python API throws an exception on MergeFromString(), + # if any of the string fields of the message can't be UTF-8 decoded. + # The C++ implementation of the API has no way to check that on + # MergeFromString and thus has no way to throw the exception. + # + # The pure Python API always returns objects of type 'unicode' (UTF-8 + # encoded), or 'bytes' (in 7 bit ASCII). + badbytes = raw.item[0].message.replace( + test_utf8_bytes, len(test_utf8_bytes) * b'\xff') + + unicode_decode_failed = False + try: + message2.MergeFromString(badbytes) + except UnicodeDecodeError: + unicode_decode_failed = True + string_field = message2.str + self.assertTrue(unicode_decode_failed or type(string_field) is bytes) + + def testBytesInTextFormat(self): + proto = unittest_pb2.TestAllTypes(optional_bytes=b'\x00\x7f\x80\xff') + self.assertEqual(u'optional_bytes: "\\000\\177\\200\\377"\n', + unicode(proto)) def testEmptyNestedMessage(self): proto = unittest_pb2.TestAllTypes() @@ -1257,16 +1753,19 @@ class ReflectionTest(unittest.TestCase): self.assertTrue(proto.HasField('optional_nested_message')) proto = unittest_pb2.TestAllTypes() - proto.optional_nested_message.MergeFromString('') + bytes_read = proto.optional_nested_message.MergeFromString(b'') + self.assertEqual(0, bytes_read) self.assertTrue(proto.HasField('optional_nested_message')) proto = unittest_pb2.TestAllTypes() - proto.optional_nested_message.ParseFromString('') + proto.optional_nested_message.ParseFromString(b'') self.assertTrue(proto.HasField('optional_nested_message')) serialized = proto.SerializeToString() proto2 = unittest_pb2.TestAllTypes() - proto2.MergeFromString(serialized) + self.assertEqual( + len(serialized), + proto2.MergeFromString(serialized)) self.assertTrue(proto2.HasField('optional_nested_message')) def testSetInParent(self): @@ -1280,12 +1779,15 @@ class ReflectionTest(unittest.TestCase): # into separate TestCase classes. -class TestAllTypesEqualityTest(unittest.TestCase): +class TestAllTypesEqualityTest(basetest.TestCase): def setUp(self): self.first_proto = unittest_pb2.TestAllTypes() self.second_proto = unittest_pb2.TestAllTypes() + def testNotHashable(self): + self.assertRaises(TypeError, hash, self.first_proto) + def testSelfEquality(self): self.assertEqual(self.first_proto, self.first_proto) @@ -1293,7 +1795,7 @@ class TestAllTypesEqualityTest(unittest.TestCase): self.assertEqual(self.first_proto, self.second_proto) -class FullProtosEqualityTest(unittest.TestCase): +class FullProtosEqualityTest(basetest.TestCase): """Equality tests using completely-full protos as a starting point.""" @@ -1303,6 +1805,9 @@ class FullProtosEqualityTest(unittest.TestCase): test_util.SetAllFields(self.first_proto) test_util.SetAllFields(self.second_proto) + def testNotHashable(self): + self.assertRaises(TypeError, hash, self.first_proto) + def testNoneNotEqual(self): self.assertNotEqual(self.first_proto, None) self.assertNotEqual(None, self.second_proto) @@ -1371,15 +1876,12 @@ class FullProtosEqualityTest(unittest.TestCase): self.first_proto.ClearField('optional_nested_message') self.second_proto.optional_nested_message.ClearField('bb') self.assertNotEqual(self.first_proto, self.second_proto) - # TODO(robinson): Replace next two lines with method - # to set the "has" bit without changing the value, - # if/when such a method exists. self.first_proto.optional_nested_message.bb = 0 self.first_proto.optional_nested_message.ClearField('bb') self.assertEqual(self.first_proto, self.second_proto) -class ExtensionEqualityTest(unittest.TestCase): +class ExtensionEqualityTest(basetest.TestCase): def testExtensionEquality(self): first_proto = unittest_pb2.TestAllExtensions() @@ -1412,7 +1914,7 @@ class ExtensionEqualityTest(unittest.TestCase): self.assertEqual(first_proto, second_proto) -class MutualRecursionEqualityTest(unittest.TestCase): +class MutualRecursionEqualityTest(basetest.TestCase): def testEqualityWithMutualRecursion(self): first_proto = unittest_pb2.TestMutualRecursionA() @@ -1424,7 +1926,7 @@ class MutualRecursionEqualityTest(unittest.TestCase): self.assertEqual(first_proto, second_proto) -class ByteSizeTest(unittest.TestCase): +class ByteSizeTest(basetest.TestCase): def setUp(self): self.proto = unittest_pb2.TestAllTypes() @@ -1438,6 +1940,14 @@ class ByteSizeTest(unittest.TestCase): def testEmptyMessage(self): self.assertEqual(0, self.proto.ByteSize()) + def testSizedOnKwargs(self): + # Use a separate message to ensure testing right after creation. + proto = unittest_pb2.TestAllTypes() + self.assertEqual(0, proto.ByteSize()) + proto_kwargs = unittest_pb2.TestAllTypes(optional_int64 = 1) + # One byte for the tag, one to encode varint 1. + self.assertEqual(2, proto_kwargs.ByteSize()) + def testVarints(self): def Test(i, expected_varint_size): self.proto.Clear() @@ -1629,10 +2139,13 @@ class ByteSizeTest(unittest.TestCase): self.assertEqual(3, self.proto.ByteSize()) self.proto.ClearField('optional_foreign_message') self.assertEqual(0, self.proto.ByteSize()) - child = self.proto.optional_foreign_message - self.proto.ClearField('optional_foreign_message') - child.c = 128 - self.assertEqual(0, self.proto.ByteSize()) + + if api_implementation.Type() == 'python': + # This is only possible in pure-Python implementation of the API. + child = self.proto.optional_foreign_message + self.proto.ClearField('optional_foreign_message') + child.c = 128 + self.assertEqual(0, self.proto.ByteSize()) # Test within extension. extension = more_extensions_pb2.optional_message_extension @@ -1698,7 +2211,6 @@ class ByteSizeTest(unittest.TestCase): self.assertEqual(19, self.packed_extended_proto.ByteSize()) -# TODO(robinson): We need cross-language serialization consistency tests. # Issues to be sure to cover include: # * Handling of unrecognized tags ("uninterpreted_bytes"). # * Handling of MessageSets. @@ -1710,14 +2222,16 @@ class ByteSizeTest(unittest.TestCase): # * Handling of empty submessages (with and without "has" # bits set). -class SerializationTest(unittest.TestCase): +class SerializationTest(basetest.TestCase): def testSerializeEmtpyMessage(self): first_proto = unittest_pb2.TestAllTypes() second_proto = unittest_pb2.TestAllTypes() serialized = first_proto.SerializeToString() self.assertEqual(first_proto.ByteSize(), len(serialized)) - second_proto.MergeFromString(serialized) + self.assertEqual( + len(serialized), + second_proto.MergeFromString(serialized)) self.assertEqual(first_proto, second_proto) def testSerializeAllFields(self): @@ -1726,7 +2240,9 @@ class SerializationTest(unittest.TestCase): test_util.SetAllFields(first_proto) serialized = first_proto.SerializeToString() self.assertEqual(first_proto.ByteSize(), len(serialized)) - second_proto.MergeFromString(serialized) + self.assertEqual( + len(serialized), + second_proto.MergeFromString(serialized)) self.assertEqual(first_proto, second_proto) def testSerializeAllExtensions(self): @@ -1734,7 +2250,19 @@ class SerializationTest(unittest.TestCase): second_proto = unittest_pb2.TestAllExtensions() test_util.SetAllExtensions(first_proto) serialized = first_proto.SerializeToString() - second_proto.MergeFromString(serialized) + self.assertEqual( + len(serialized), + second_proto.MergeFromString(serialized)) + self.assertEqual(first_proto, second_proto) + + def testSerializeWithOptionalGroup(self): + first_proto = unittest_pb2.TestAllTypes() + second_proto = unittest_pb2.TestAllTypes() + first_proto.optionalgroup.a = 242 + serialized = first_proto.SerializeToString() + self.assertEqual( + len(serialized), + second_proto.MergeFromString(serialized)) self.assertEqual(first_proto, second_proto) def testSerializeNegativeValues(self): @@ -1753,6 +2281,10 @@ class SerializationTest(unittest.TestCase): self.assertEqual(first_proto, second_proto) def testParseTruncated(self): + # This test is only applicable for the Python implementation of the API. + if api_implementation.Type() != 'python': + return + first_proto = unittest_pb2.TestAllTypes() test_util.SetAllFields(first_proto) serialized = first_proto.SerializeToString() @@ -1822,7 +2354,9 @@ class SerializationTest(unittest.TestCase): second_proto.optional_int32 = 100 second_proto.optional_nested_message.bb = 999 - second_proto.MergeFromString(serialized) + bytes_parsed = second_proto.MergeFromString(serialized) + self.assertEqual(len(serialized), bytes_parsed) + # Ensure that we append to repeated fields. self.assertEqual(['baz', 'foobar'], list(second_proto.repeated_string)) # Ensure that we overwrite nonrepeatd scalars. @@ -1847,20 +2381,28 @@ class SerializationTest(unittest.TestCase): raw = unittest_mset_pb2.RawMessageSet() self.assertEqual(False, raw.DESCRIPTOR.GetOptions().message_set_wire_format) - raw.MergeFromString(serialized) + self.assertEqual( + len(serialized), + raw.MergeFromString(serialized)) self.assertEqual(2, len(raw.item)) message1 = unittest_mset_pb2.TestMessageSetExtension1() - message1.MergeFromString(raw.item[0].message) + self.assertEqual( + len(raw.item[0].message), + message1.MergeFromString(raw.item[0].message)) self.assertEqual(123, message1.i) message2 = unittest_mset_pb2.TestMessageSetExtension2() - message2.MergeFromString(raw.item[1].message) + self.assertEqual( + len(raw.item[1].message), + message2.MergeFromString(raw.item[1].message)) self.assertEqual('foo', message2.str) # Deserialize using the MessageSet wire format. proto2 = unittest_mset_pb2.TestMessageSet() - proto2.MergeFromString(serialized) + self.assertEqual( + len(serialized), + proto2.MergeFromString(serialized)) self.assertEqual(123, proto2.Extensions[extension1].i) self.assertEqual('foo', proto2.Extensions[extension2].str) @@ -1900,7 +2442,9 @@ class SerializationTest(unittest.TestCase): # Parse message using the message set wire format. proto = unittest_mset_pb2.TestMessageSet() - proto.MergeFromString(serialized) + self.assertEqual( + len(serialized), + proto.MergeFromString(serialized)) # Check that the message parsed well. extension_message1 = unittest_mset_pb2.TestMessageSetExtension1 @@ -1918,7 +2462,9 @@ class SerializationTest(unittest.TestCase): proto2 = unittest_pb2.TestEmptyMessage() # Parsing this message should succeed. - proto2.MergeFromString(serialized) + self.assertEqual( + len(serialized), + proto2.MergeFromString(serialized)) # Now test with a int64 field set. proto = unittest_pb2.TestAllTypes() @@ -1928,13 +2474,15 @@ class SerializationTest(unittest.TestCase): # unknown. proto2 = unittest_pb2.TestEmptyMessage() # Parsing this message should succeed. - proto2.MergeFromString(serialized) + self.assertEqual( + len(serialized), + proto2.MergeFromString(serialized)) def _CheckRaises(self, exc_class, callable_obj, exception): """This method checks if the excpetion type and message are as expected.""" try: callable_obj() - except exc_class, ex: + except exc_class as ex: # Check if the exception message is the right one. self.assertEqual(exception, str(ex)) return @@ -1946,15 +2494,22 @@ class SerializationTest(unittest.TestCase): self._CheckRaises( message.EncodeError, proto.SerializeToString, - 'Message is missing required fields: a,b,c') + 'Message protobuf_unittest.TestRequired is missing required fields: ' + 'a,b,c') # Shouldn't raise exceptions. partial = proto.SerializePartialToString() + proto2 = unittest_pb2.TestRequired() + self.assertFalse(proto2.HasField('a')) + # proto2 ParseFromString does not check that required fields are set. + proto2.ParseFromString(partial) + self.assertFalse(proto2.HasField('a')) + proto.a = 1 self._CheckRaises( message.EncodeError, proto.SerializeToString, - 'Message is missing required fields: b,c') + 'Message protobuf_unittest.TestRequired is missing required fields: b,c') # Shouldn't raise exceptions. partial = proto.SerializePartialToString() @@ -1962,7 +2517,7 @@ class SerializationTest(unittest.TestCase): self._CheckRaises( message.EncodeError, proto.SerializeToString, - 'Message is missing required fields: c') + 'Message protobuf_unittest.TestRequired is missing required fields: c') # Shouldn't raise exceptions. partial = proto.SerializePartialToString() @@ -1972,11 +2527,15 @@ class SerializationTest(unittest.TestCase): partial = proto.SerializePartialToString() proto2 = unittest_pb2.TestRequired() - proto2.MergeFromString(serialized) + self.assertEqual( + len(serialized), + proto2.MergeFromString(serialized)) self.assertEqual(1, proto2.a) self.assertEqual(2, proto2.b) self.assertEqual(3, proto2.c) - proto2.ParseFromString(partial) + self.assertEqual( + len(partial), + proto2.MergeFromString(partial)) self.assertEqual(1, proto2.a) self.assertEqual(2, proto2.b) self.assertEqual(3, proto2.c) @@ -1991,7 +2550,8 @@ class SerializationTest(unittest.TestCase): self._CheckRaises( message.EncodeError, proto.SerializeToString, - 'Message is missing required fields: ' + 'Message protobuf_unittest.TestRequiredForeign ' + 'is missing required fields: ' 'optional_message.b,optional_message.c') proto.optional_message.b = 2 @@ -2003,7 +2563,7 @@ class SerializationTest(unittest.TestCase): self._CheckRaises( message.EncodeError, proto.SerializeToString, - 'Message is missing required fields: ' + 'Message protobuf_unittest.TestRequiredForeign is missing required fields: ' 'repeated_message[0].b,repeated_message[0].c,' 'repeated_message[1].a,repeated_message[1].c') @@ -2043,7 +2603,9 @@ class SerializationTest(unittest.TestCase): second_proto.packed_double.extend([1.0, 2.0]) second_proto.packed_sint32.append(4) - second_proto.MergeFromString(serialized) + self.assertEqual( + len(serialized), + second_proto.MergeFromString(serialized)) self.assertEqual([3, 1, 2], second_proto.packed_int32) self.assertEqual([1.0, 2.0, 3.0], second_proto.packed_double) self.assertEqual([4], second_proto.packed_sint32) @@ -2076,7 +2638,10 @@ class SerializationTest(unittest.TestCase): unpacked = unittest_pb2.TestUnpackedTypes() test_util.SetAllUnpackedFields(unpacked) packed = unittest_pb2.TestPackedTypes() - packed.MergeFromString(unpacked.SerializeToString()) + serialized = unpacked.SerializeToString() + self.assertEqual( + len(serialized), + packed.MergeFromString(serialized)) expected = unittest_pb2.TestPackedTypes() test_util.SetAllPackedFields(expected) self.assertEqual(expected, packed) @@ -2085,7 +2650,10 @@ class SerializationTest(unittest.TestCase): packed = unittest_pb2.TestPackedTypes() test_util.SetAllPackedFields(packed) unpacked = unittest_pb2.TestUnpackedTypes() - unpacked.MergeFromString(packed.SerializeToString()) + serialized = packed.SerializeToString() + self.assertEqual( + len(serialized), + unpacked.MergeFromString(serialized)) expected = unittest_pb2.TestUnpackedTypes() test_util.SetAllUnpackedFields(expected) self.assertEqual(expected, unpacked) @@ -2137,7 +2705,7 @@ class SerializationTest(unittest.TestCase): optional_int32=1, optional_string='foo', optional_bool=True, - optional_bytes='bar', + optional_bytes=b'bar', optional_nested_message=unittest_pb2.TestAllTypes.NestedMessage(bb=1), optional_foreign_message=unittest_pb2.ForeignMessage(c=1), optional_nested_enum=unittest_pb2.TestAllTypes.FOO, @@ -2155,7 +2723,7 @@ class SerializationTest(unittest.TestCase): self.assertEqual(1, proto.optional_int32) self.assertEqual('foo', proto.optional_string) self.assertEqual(True, proto.optional_bool) - self.assertEqual('bar', proto.optional_bytes) + self.assertEqual(b'bar', proto.optional_bytes) self.assertEqual(1, proto.optional_nested_message.bb) self.assertEqual(1, proto.optional_foreign_message.c) self.assertEqual(unittest_pb2.TestAllTypes.FOO, @@ -2205,7 +2773,7 @@ class SerializationTest(unittest.TestCase): self.assertEqual(3, proto.repeated_int32[2]) -class OptionsTest(unittest.TestCase): +class OptionsTest(basetest.TestCase): def testMessageOptions(self): proto = unittest_mset_pb2.TestMessageSet() @@ -2232,5 +2800,135 @@ class OptionsTest(unittest.TestCase): +class ClassAPITest(basetest.TestCase): + + def testMakeClassWithNestedDescriptor(self): + leaf_desc = descriptor.Descriptor('leaf', 'package.parent.child.leaf', '', + containing_type=None, fields=[], + nested_types=[], enum_types=[], + extensions=[]) + child_desc = descriptor.Descriptor('child', 'package.parent.child', '', + containing_type=None, fields=[], + nested_types=[leaf_desc], enum_types=[], + extensions=[]) + sibling_desc = descriptor.Descriptor('sibling', 'package.parent.sibling', + '', containing_type=None, fields=[], + nested_types=[], enum_types=[], + extensions=[]) + parent_desc = descriptor.Descriptor('parent', 'package.parent', '', + containing_type=None, fields=[], + nested_types=[child_desc, sibling_desc], + enum_types=[], extensions=[]) + message_class = reflection.MakeClass(parent_desc) + self.assertIn('child', message_class.__dict__) + self.assertIn('sibling', message_class.__dict__) + self.assertIn('leaf', message_class.child.__dict__) + + def _GetSerializedFileDescriptor(self, name): + """Get a serialized representation of a test FileDescriptorProto. + + Args: + name: All calls to this must use a unique message name, to avoid + collisions in the cpp descriptor pool. + Returns: + A string containing the serialized form of a test FileDescriptorProto. + """ + file_descriptor_str = ( + 'message_type {' + ' name: "' + name + '"' + ' field {' + ' name: "flat"' + ' number: 1' + ' label: LABEL_REPEATED' + ' type: TYPE_UINT32' + ' }' + ' field {' + ' name: "bar"' + ' number: 2' + ' label: LABEL_OPTIONAL' + ' type: TYPE_MESSAGE' + ' type_name: "Bar"' + ' }' + ' nested_type {' + ' name: "Bar"' + ' field {' + ' name: "baz"' + ' number: 3' + ' label: LABEL_OPTIONAL' + ' type: TYPE_MESSAGE' + ' type_name: "Baz"' + ' }' + ' nested_type {' + ' name: "Baz"' + ' enum_type {' + ' name: "deep_enum"' + ' value {' + ' name: "VALUE_A"' + ' number: 0' + ' }' + ' }' + ' field {' + ' name: "deep"' + ' number: 4' + ' label: LABEL_OPTIONAL' + ' type: TYPE_UINT32' + ' }' + ' }' + ' }' + '}') + file_descriptor = descriptor_pb2.FileDescriptorProto() + text_format.Merge(file_descriptor_str, file_descriptor) + return file_descriptor.SerializeToString() + + def testParsingFlatClassWithExplicitClassDeclaration(self): + """Test that the generated class can parse a flat message.""" + file_descriptor = descriptor_pb2.FileDescriptorProto() + file_descriptor.ParseFromString(self._GetSerializedFileDescriptor('A')) + msg_descriptor = descriptor.MakeDescriptor( + file_descriptor.message_type[0]) + + class MessageClass(message.Message): + __metaclass__ = reflection.GeneratedProtocolMessageType + DESCRIPTOR = msg_descriptor + msg = MessageClass() + msg_str = ( + 'flat: 0 ' + 'flat: 1 ' + 'flat: 2 ') + text_format.Merge(msg_str, msg) + self.assertEqual(msg.flat, [0, 1, 2]) + + def testParsingFlatClass(self): + """Test that the generated class can parse a flat message.""" + file_descriptor = descriptor_pb2.FileDescriptorProto() + file_descriptor.ParseFromString(self._GetSerializedFileDescriptor('B')) + msg_descriptor = descriptor.MakeDescriptor( + file_descriptor.message_type[0]) + msg_class = reflection.MakeClass(msg_descriptor) + msg = msg_class() + msg_str = ( + 'flat: 0 ' + 'flat: 1 ' + 'flat: 2 ') + text_format.Merge(msg_str, msg) + self.assertEqual(msg.flat, [0, 1, 2]) + + def testParsingNestedClass(self): + """Test that the generated class can parse a nested message.""" + file_descriptor = descriptor_pb2.FileDescriptorProto() + file_descriptor.ParseFromString(self._GetSerializedFileDescriptor('C')) + msg_descriptor = descriptor.MakeDescriptor( + file_descriptor.message_type[0]) + msg_class = reflection.MakeClass(msg_descriptor) + msg = msg_class() + msg_str = ( + 'bar {' + ' baz {' + ' deep: 4' + ' }' + '}') + text_format.Merge(msg_str, msg) + self.assertEqual(msg.bar.baz.deep, 4) + if __name__ == '__main__': - unittest.main() + basetest.main() diff --git a/python/google/protobuf/internal/service_reflection_test.py b/python/google/protobuf/internal/service_reflection_test.py index e04f825..ef0981d 100755 --- a/python/google/protobuf/internal/service_reflection_test.py +++ b/python/google/protobuf/internal/service_reflection_test.py @@ -34,13 +34,13 @@ __author__ = 'petar@google.com (Petar Petrov)' -import unittest +from google.apputils import basetest from google.protobuf import unittest_pb2 from google.protobuf import service_reflection from google.protobuf import service -class FooUnitTest(unittest.TestCase): +class FooUnitTest(basetest.TestCase): def testService(self): class MockRpcChannel(service.RpcChannel): @@ -133,4 +133,4 @@ class FooUnitTest(unittest.TestCase): if __name__ == '__main__': - unittest.main() + basetest.main() diff --git a/python/google/protobuf/internal/symbol_database_test.py b/python/google/protobuf/internal/symbol_database_test.py new file mode 100644 index 0000000..80bc8d6 --- /dev/null +++ b/python/google/protobuf/internal/symbol_database_test.py @@ -0,0 +1,120 @@ +#! /usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Tests for google.protobuf.symbol_database.""" + +from google.apputils import basetest +from google.protobuf import unittest_pb2 +from google.protobuf import symbol_database + + +class SymbolDatabaseTest(basetest.TestCase): + + def _Database(self): + db = symbol_database.SymbolDatabase() + # Register representative types from unittest_pb2. + db.RegisterFileDescriptor(unittest_pb2.DESCRIPTOR) + db.RegisterMessage(unittest_pb2.TestAllTypes) + db.RegisterMessage(unittest_pb2.TestAllTypes.NestedMessage) + db.RegisterMessage(unittest_pb2.TestAllTypes.OptionalGroup) + db.RegisterMessage(unittest_pb2.TestAllTypes.RepeatedGroup) + db.RegisterEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR) + db.RegisterEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR) + return db + + def testGetPrototype(self): + instance = self._Database().GetPrototype( + unittest_pb2.TestAllTypes.DESCRIPTOR) + self.assertTrue(instance is unittest_pb2.TestAllTypes) + + def testGetMessages(self): + messages = self._Database().GetMessages( + ['google/protobuf/unittest.proto']) + self.assertTrue( + unittest_pb2.TestAllTypes is + messages['protobuf_unittest.TestAllTypes']) + + def testGetSymbol(self): + self.assertEquals( + unittest_pb2.TestAllTypes, self._Database().GetSymbol( + 'protobuf_unittest.TestAllTypes')) + self.assertEquals( + unittest_pb2.TestAllTypes.NestedMessage, self._Database().GetSymbol( + 'protobuf_unittest.TestAllTypes.NestedMessage')) + self.assertEquals( + unittest_pb2.TestAllTypes.OptionalGroup, self._Database().GetSymbol( + 'protobuf_unittest.TestAllTypes.OptionalGroup')) + self.assertEquals( + unittest_pb2.TestAllTypes.RepeatedGroup, self._Database().GetSymbol( + 'protobuf_unittest.TestAllTypes.RepeatedGroup')) + + def testEnums(self): + # Check registration of types in the pool. + self.assertEquals( + 'protobuf_unittest.ForeignEnum', + self._Database().pool.FindEnumTypeByName( + 'protobuf_unittest.ForeignEnum').full_name) + self.assertEquals( + 'protobuf_unittest.TestAllTypes.NestedEnum', + self._Database().pool.FindEnumTypeByName( + 'protobuf_unittest.TestAllTypes.NestedEnum').full_name) + + def testFindMessageTypeByName(self): + self.assertEquals( + 'protobuf_unittest.TestAllTypes', + self._Database().pool.FindMessageTypeByName( + 'protobuf_unittest.TestAllTypes').full_name) + self.assertEquals( + 'protobuf_unittest.TestAllTypes.NestedMessage', + self._Database().pool.FindMessageTypeByName( + 'protobuf_unittest.TestAllTypes.NestedMessage').full_name) + + def testFindFindContainingSymbol(self): + # Lookup based on either enum or message. + self.assertEquals( + 'google/protobuf/unittest.proto', + self._Database().pool.FindFileContainingSymbol( + 'protobuf_unittest.TestAllTypes.NestedEnum').name) + self.assertEquals( + 'google/protobuf/unittest.proto', + self._Database().pool.FindFileContainingSymbol( + 'protobuf_unittest.TestAllTypes').name) + + def testFindFileByName(self): + self.assertEquals( + 'google/protobuf/unittest.proto', + self._Database().pool.FindFileByName( + 'google/protobuf/unittest.proto').name) + + +if __name__ == '__main__': + basetest.main() diff --git a/python/google/protobuf/internal/test_bad_identifiers.proto b/python/google/protobuf/internal/test_bad_identifiers.proto new file mode 100644 index 0000000..6a82299 --- /dev/null +++ b/python/google/protobuf/internal/test_bad_identifiers.proto @@ -0,0 +1,52 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) + + +package protobuf_unittest; + +option py_generic_services = true; + +message TestBadIdentifiers { + extensions 100 to max; +} + +// Make sure these reasonable extension names don't conflict with internal +// variables. +extend TestBadIdentifiers { + optional string message = 100 [default="foo"]; + optional string descriptor = 101 [default="bar"]; + optional string reflection = 102 [default="baz"]; + optional string service = 103 [default="qux"]; +} + +message AnotherMessage {} +service AnotherService {} diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py index 1df1619..350d1c6 100755 --- a/python/google/protobuf/internal/test_util.py +++ b/python/google/protobuf/internal/test_util.py @@ -42,8 +42,8 @@ from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_pb2 -def SetAllFields(message): - """Sets every field in the message to a unique value. +def SetAllNonLazyFields(message): + """Sets every non-lazy field in the message to a unique value. Args: message: A unittest_pb2.TestAllTypes instance. @@ -66,26 +66,21 @@ def SetAllFields(message): message.optional_float = 111 message.optional_double = 112 message.optional_bool = True - # TODO(robinson): Firmly spec out and test how - # protos interact with unicode. One specific example: - # what happens if we change the literal below to - # u'115'? What *should* happen? Still some discussion - # to finish with Kenton about bytes vs. strings - # and forcing everything to be utf8. :-/ - message.optional_string = '115' - message.optional_bytes = '116' + message.optional_string = u'115' + message.optional_bytes = b'116' message.optionalgroup.a = 117 message.optional_nested_message.bb = 118 message.optional_foreign_message.c = 119 message.optional_import_message.d = 120 + message.optional_public_import_message.e = 126 message.optional_nested_enum = unittest_pb2.TestAllTypes.BAZ message.optional_foreign_enum = unittest_pb2.FOREIGN_BAZ message.optional_import_enum = unittest_import_pb2.IMPORT_BAZ - message.optional_string_piece = '124' - message.optional_cord = '125' + message.optional_string_piece = u'124' + message.optional_cord = u'125' # # Repeated fields. @@ -104,20 +99,21 @@ def SetAllFields(message): message.repeated_float.append(211) message.repeated_double.append(212) message.repeated_bool.append(True) - message.repeated_string.append('215') - message.repeated_bytes.append('216') + message.repeated_string.append(u'215') + message.repeated_bytes.append(b'216') message.repeatedgroup.add().a = 217 message.repeated_nested_message.add().bb = 218 message.repeated_foreign_message.add().c = 219 message.repeated_import_message.add().d = 220 + message.repeated_lazy_message.add().bb = 227 message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR) message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAR) message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAR) - message.repeated_string_piece.append('224') - message.repeated_cord.append('225') + message.repeated_string_piece.append(u'224') + message.repeated_cord.append(u'225') # Add a second one of each field. message.repeated_int32.append(301) @@ -133,20 +129,21 @@ def SetAllFields(message): message.repeated_float.append(311) message.repeated_double.append(312) message.repeated_bool.append(False) - message.repeated_string.append('315') - message.repeated_bytes.append('316') + message.repeated_string.append(u'315') + message.repeated_bytes.append(b'316') message.repeatedgroup.add().a = 317 message.repeated_nested_message.add().bb = 318 message.repeated_foreign_message.add().c = 319 message.repeated_import_message.add().d = 320 + message.repeated_lazy_message.add().bb = 327 message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAZ) message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAZ) message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAZ) - message.repeated_string_piece.append('324') - message.repeated_cord.append('325') + message.repeated_string_piece.append(u'324') + message.repeated_cord.append(u'325') # # Fields that have defaults. @@ -166,7 +163,7 @@ def SetAllFields(message): message.default_double = 412 message.default_bool = False message.default_string = '415' - message.default_bytes = '416' + message.default_bytes = b'416' message.default_nested_enum = unittest_pb2.TestAllTypes.FOO message.default_foreign_enum = unittest_pb2.FOREIGN_FOO @@ -175,6 +172,16 @@ def SetAllFields(message): message.default_string_piece = '424' message.default_cord = '425' + message.oneof_uint32 = 601 + message.oneof_nested_message.bb = 602 + message.oneof_string = '603' + message.oneof_bytes = b'604' + + +def SetAllFields(message): + SetAllNonLazyFields(message) + message.optional_lazy_message.bb = 127 + def SetAllExtensions(message): """Sets every extension in the message to a unique value. @@ -204,21 +211,23 @@ def SetAllExtensions(message): extensions[pb2.optional_float_extension] = 111 extensions[pb2.optional_double_extension] = 112 extensions[pb2.optional_bool_extension] = True - extensions[pb2.optional_string_extension] = '115' - extensions[pb2.optional_bytes_extension] = '116' + extensions[pb2.optional_string_extension] = u'115' + extensions[pb2.optional_bytes_extension] = b'116' extensions[pb2.optionalgroup_extension].a = 117 extensions[pb2.optional_nested_message_extension].bb = 118 extensions[pb2.optional_foreign_message_extension].c = 119 extensions[pb2.optional_import_message_extension].d = 120 + extensions[pb2.optional_public_import_message_extension].e = 126 + extensions[pb2.optional_lazy_message_extension].bb = 127 extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ extensions[pb2.optional_foreign_enum_extension] = pb2.FOREIGN_BAZ extensions[pb2.optional_import_enum_extension] = import_pb2.IMPORT_BAZ - extensions[pb2.optional_string_piece_extension] = '124' - extensions[pb2.optional_cord_extension] = '125' + extensions[pb2.optional_string_piece_extension] = u'124' + extensions[pb2.optional_cord_extension] = u'125' # # Repeated fields. @@ -237,20 +246,21 @@ def SetAllExtensions(message): extensions[pb2.repeated_float_extension].append(211) extensions[pb2.repeated_double_extension].append(212) extensions[pb2.repeated_bool_extension].append(True) - extensions[pb2.repeated_string_extension].append('215') - extensions[pb2.repeated_bytes_extension].append('216') + extensions[pb2.repeated_string_extension].append(u'215') + extensions[pb2.repeated_bytes_extension].append(b'216') extensions[pb2.repeatedgroup_extension].add().a = 217 extensions[pb2.repeated_nested_message_extension].add().bb = 218 extensions[pb2.repeated_foreign_message_extension].add().c = 219 extensions[pb2.repeated_import_message_extension].add().d = 220 + extensions[pb2.repeated_lazy_message_extension].add().bb = 227 extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAR) extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAR) extensions[pb2.repeated_import_enum_extension].append(import_pb2.IMPORT_BAR) - extensions[pb2.repeated_string_piece_extension].append('224') - extensions[pb2.repeated_cord_extension].append('225') + extensions[pb2.repeated_string_piece_extension].append(u'224') + extensions[pb2.repeated_cord_extension].append(u'225') # Append a second one of each field. extensions[pb2.repeated_int32_extension].append(301) @@ -266,20 +276,21 @@ def SetAllExtensions(message): extensions[pb2.repeated_float_extension].append(311) extensions[pb2.repeated_double_extension].append(312) extensions[pb2.repeated_bool_extension].append(False) - extensions[pb2.repeated_string_extension].append('315') - extensions[pb2.repeated_bytes_extension].append('316') + extensions[pb2.repeated_string_extension].append(u'315') + extensions[pb2.repeated_bytes_extension].append(b'316') extensions[pb2.repeatedgroup_extension].add().a = 317 extensions[pb2.repeated_nested_message_extension].add().bb = 318 extensions[pb2.repeated_foreign_message_extension].add().c = 319 extensions[pb2.repeated_import_message_extension].add().d = 320 + extensions[pb2.repeated_lazy_message_extension].add().bb = 327 extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAZ) extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAZ) extensions[pb2.repeated_import_enum_extension].append(import_pb2.IMPORT_BAZ) - extensions[pb2.repeated_string_piece_extension].append('324') - extensions[pb2.repeated_cord_extension].append('325') + extensions[pb2.repeated_string_piece_extension].append(u'324') + extensions[pb2.repeated_cord_extension].append(u'325') # # Fields with defaults. @@ -298,16 +309,21 @@ def SetAllExtensions(message): extensions[pb2.default_float_extension] = 411 extensions[pb2.default_double_extension] = 412 extensions[pb2.default_bool_extension] = False - extensions[pb2.default_string_extension] = '415' - extensions[pb2.default_bytes_extension] = '416' + extensions[pb2.default_string_extension] = u'415' + extensions[pb2.default_bytes_extension] = b'416' extensions[pb2.default_nested_enum_extension] = pb2.TestAllTypes.FOO extensions[pb2.default_foreign_enum_extension] = pb2.FOREIGN_FOO extensions[pb2.default_import_enum_extension] = import_pb2.IMPORT_FOO - extensions[pb2.default_string_piece_extension] = '424' + extensions[pb2.default_string_piece_extension] = u'424' extensions[pb2.default_cord_extension] = '425' + extensions[pb2.oneof_uint32_extension] = 601 + extensions[pb2.oneof_nested_message_extension].bb = 602 + extensions[pb2.oneof_string_extension] = u'603' + extensions[pb2.oneof_bytes_extension] = b'604' + def SetAllFieldsAndExtensions(message): """Sets every field and extension in the message to a unique value. @@ -346,7 +362,7 @@ def ExpectAllFieldsAndExtensionsInOrder(serialized): message.my_float = 1.0 expected_strings.append(message.SerializeToString()) message.Clear() - expected = ''.join(expected_strings) + expected = b''.join(expected_strings) if expected != serialized: raise ValueError('Expected %r, found %r' % (expected, serialized)) @@ -401,12 +417,14 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertEqual(112, message.optional_double) test_case.assertEqual(True, message.optional_bool) test_case.assertEqual('115', message.optional_string) - test_case.assertEqual('116', message.optional_bytes) + test_case.assertEqual(b'116', message.optional_bytes) test_case.assertEqual(117, message.optionalgroup.a) test_case.assertEqual(118, message.optional_nested_message.bb) test_case.assertEqual(119, message.optional_foreign_message.c) test_case.assertEqual(120, message.optional_import_message.d) + test_case.assertEqual(126, message.optional_public_import_message.e) + test_case.assertEqual(127, message.optional_lazy_message.bb) test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ, message.optional_nested_enum) @@ -458,12 +476,13 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertEqual(212, message.repeated_double[0]) test_case.assertEqual(True, message.repeated_bool[0]) test_case.assertEqual('215', message.repeated_string[0]) - test_case.assertEqual('216', message.repeated_bytes[0]) + test_case.assertEqual(b'216', message.repeated_bytes[0]) test_case.assertEqual(217, message.repeatedgroup[0].a) test_case.assertEqual(218, message.repeated_nested_message[0].bb) test_case.assertEqual(219, message.repeated_foreign_message[0].c) test_case.assertEqual(220, message.repeated_import_message[0].d) + test_case.assertEqual(227, message.repeated_lazy_message[0].bb) test_case.assertEqual(unittest_pb2.TestAllTypes.BAR, message.repeated_nested_enum[0]) @@ -486,12 +505,13 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertEqual(312, message.repeated_double[1]) test_case.assertEqual(False, message.repeated_bool[1]) test_case.assertEqual('315', message.repeated_string[1]) - test_case.assertEqual('316', message.repeated_bytes[1]) + test_case.assertEqual(b'316', message.repeated_bytes[1]) test_case.assertEqual(317, message.repeatedgroup[1].a) test_case.assertEqual(318, message.repeated_nested_message[1].bb) test_case.assertEqual(319, message.repeated_foreign_message[1].c) test_case.assertEqual(320, message.repeated_import_message[1].d) + test_case.assertEqual(327, message.repeated_lazy_message[1].bb) test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ, message.repeated_nested_enum[1]) @@ -536,7 +556,7 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertEqual(412, message.default_double) test_case.assertEqual(False, message.default_bool) test_case.assertEqual('415', message.default_string) - test_case.assertEqual('416', message.default_bytes) + test_case.assertEqual(b'416', message.default_bytes) test_case.assertEqual(unittest_pb2.TestAllTypes.FOO, message.default_nested_enum) @@ -545,6 +565,7 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertEqual(unittest_import_pb2.IMPORT_FOO, message.default_import_enum) + def GoldenFile(filename): """Finds the given golden file and returns a file object representing it.""" @@ -558,9 +579,15 @@ def GoldenFile(filename): path = os.path.join(path, '..') raise RuntimeError( - 'Could not find golden files. This test must be run from within the ' - 'protobuf source package so that it can read test data files from the ' - 'C++ source tree.') + 'Could not find golden files. This test must be run from within the ' + 'protobuf source package so that it can read test data files from the ' + 'C++ source tree.') + + +def GoldenFileData(filename): + """Finds the given golden file and returns its contents.""" + with GoldenFile(filename) as f: + return f.read() def SetAllPackedFields(message): diff --git a/python/google/protobuf/internal/text_encoding_test.py b/python/google/protobuf/internal/text_encoding_test.py new file mode 100755 index 0000000..ba0e45d --- /dev/null +++ b/python/google/protobuf/internal/text_encoding_test.py @@ -0,0 +1,68 @@ +#! /usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Tests for google.protobuf.text_encoding.""" + +from google.apputils import basetest +from google.protobuf import text_encoding + +TEST_VALUES = [ + ("foo\\rbar\\nbaz\\t", + "foo\\rbar\\nbaz\\t", + b"foo\rbar\nbaz\t"), + ("\\'full of \\\"sound\\\" and \\\"fury\\\"\\'", + "\\'full of \\\"sound\\\" and \\\"fury\\\"\\'", + b"'full of \"sound\" and \"fury\"'"), + ("signi\\\\fying\\\\ nothing\\\\", + "signi\\\\fying\\\\ nothing\\\\", + b"signi\\fying\\ nothing\\"), + ("\\010\\t\\n\\013\\014\\r", + "\x08\\t\\n\x0b\x0c\\r", + b"\010\011\012\013\014\015")] + + +class TextEncodingTestCase(basetest.TestCase): + def testCEscape(self): + for escaped, escaped_utf8, unescaped in TEST_VALUES: + self.assertEquals(escaped, + text_encoding.CEscape(unescaped, as_utf8=False)) + self.assertEquals(escaped_utf8, + text_encoding.CEscape(unescaped, as_utf8=True)) + + def testCUnescape(self): + for escaped, escaped_utf8, unescaped in TEST_VALUES: + self.assertEquals(unescaped, text_encoding.CUnescape(escaped)) + self.assertEquals(unescaped, text_encoding.CUnescape(escaped_utf8)) + + +if __name__ == "__main__": + basetest.main() diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index e0991cb..d27ff7a 100755 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -34,48 +34,71 @@ __author__ = 'kenton@google.com (Kenton Varda)' -import difflib +import re -import unittest +from google.apputils import basetest from google.protobuf import text_format +from google.protobuf.internal import api_implementation from google.protobuf.internal import test_util from google.protobuf import unittest_pb2 from google.protobuf import unittest_mset_pb2 +class TextFormatTest(basetest.TestCase): -class TextFormatTest(unittest.TestCase): def ReadGolden(self, golden_filename): - f = test_util.GoldenFile(golden_filename) - golden_lines = f.readlines() - f.close() - return golden_lines + with test_util.GoldenFile(golden_filename) as f: + return (f.readlines() if str is bytes else # PY3 + [golden_line.decode('utf-8') for golden_line in f]) def CompareToGoldenFile(self, text, golden_filename): golden_lines = self.ReadGolden(golden_filename) - self.CompareToGoldenLines(text, golden_lines) + self.assertMultiLineEqual(text, ''.join(golden_lines)) def CompareToGoldenText(self, text, golden_text): - self.CompareToGoldenLines(text, golden_text.splitlines(1)) - - def CompareToGoldenLines(self, text, golden_lines): - actual_lines = text.splitlines(1) - self.assertEqual(golden_lines, actual_lines, - "Text doesn't match golden. Diff:\n" + - ''.join(difflib.ndiff(golden_lines, actual_lines))) + self.assertMultiLineEqual(text, golden_text) def testPrintAllFields(self): message = unittest_pb2.TestAllTypes() test_util.SetAllFields(message) self.CompareToGoldenFile( - self.RemoveRedundantZeros(text_format.MessageToString(message)), - 'text_format_unittest_data.txt') + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'text_format_unittest_data_oneof_implemented.txt') + + def testPrintInIndexOrder(self): + message = unittest_pb2.TestFieldOrderings() + message.my_string = '115' + message.my_int = 101 + message.my_float = 111 + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_format.MessageToString( + message, use_index_order=True)), + 'my_string: \"115\"\nmy_int: 101\nmy_float: 111\n') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_format.MessageToString( + message)), 'my_int: 101\nmy_string: \"115\"\nmy_float: 111\n') def testPrintAllExtensions(self): message = unittest_pb2.TestAllExtensions() test_util.SetAllExtensions(message) self.CompareToGoldenFile( - self.RemoveRedundantZeros(text_format.MessageToString(message)), - 'text_format_unittest_extensions_data.txt') + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'text_format_unittest_extensions_data.txt') + + def testPrintAllFieldsPointy(self): + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros( + text_format.MessageToString(message, pointy_brackets=True)), + 'text_format_unittest_data_pointy_oneof.txt') + + def testPrintAllExtensionsPointy(self): + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros(text_format.MessageToString( + message, pointy_brackets=True)), + 'text_format_unittest_extensions_data_pointy.txt') def testPrintMessageSet(self): message = unittest_mset_pb2.TestMessageSetContainer() @@ -83,33 +106,179 @@ class TextFormatTest(unittest.TestCase): ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension message.message_set.Extensions[ext1].i = 23 message.message_set.Extensions[ext2].str = 'foo' - self.CompareToGoldenText(text_format.MessageToString(message), - 'message_set {\n' - ' [protobuf_unittest.TestMessageSetExtension1] {\n' - ' i: 23\n' - ' }\n' - ' [protobuf_unittest.TestMessageSetExtension2] {\n' - ' str: \"foo\"\n' - ' }\n' - '}\n') + self.CompareToGoldenText( + text_format.MessageToString(message), + 'message_set {\n' + ' [protobuf_unittest.TestMessageSetExtension1] {\n' + ' i: 23\n' + ' }\n' + ' [protobuf_unittest.TestMessageSetExtension2] {\n' + ' str: \"foo\"\n' + ' }\n' + '}\n') def testPrintExotic(self): message = unittest_pb2.TestAllTypes() - message.repeated_int64.append(-9223372036854775808); - message.repeated_uint64.append(18446744073709551615); - message.repeated_double.append(123.456); - message.repeated_double.append(1.23e22); - message.repeated_double.append(1.23e-18); - message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'\"'); + message.repeated_int64.append(-9223372036854775808) + message.repeated_uint64.append(18446744073709551615) + message.repeated_double.append(123.456) + message.repeated_double.append(1.23e22) + message.repeated_double.append(1.23e-18) + message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"') + message.repeated_string.append(u'\u00fc\ua71f') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'repeated_int64: -9223372036854775808\n' + 'repeated_uint64: 18446744073709551615\n' + 'repeated_double: 123.456\n' + 'repeated_double: 1.23e+22\n' + 'repeated_double: 1.23e-18\n' + 'repeated_string:' + ' "\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n' + 'repeated_string: "\\303\\274\\352\\234\\237"\n') + + def testPrintExoticUnicodeSubclass(self): + class UnicodeSub(unicode): + pass + message = unittest_pb2.TestAllTypes() + message.repeated_string.append(UnicodeSub(u'\u00fc\ua71f')) + self.CompareToGoldenText( + text_format.MessageToString(message), + 'repeated_string: "\\303\\274\\352\\234\\237"\n') + + def testPrintNestedMessageAsOneLine(self): + message = unittest_pb2.TestAllTypes() + msg = message.repeated_nested_message.add() + msg.bb = 42 + self.CompareToGoldenText( + text_format.MessageToString(message, as_one_line=True), + 'repeated_nested_message { bb: 42 }') + + def testPrintRepeatedFieldsAsOneLine(self): + message = unittest_pb2.TestAllTypes() + message.repeated_int32.append(1) + message.repeated_int32.append(1) + message.repeated_int32.append(3) + message.repeated_string.append("Google") + message.repeated_string.append("Zurich") self.CompareToGoldenText( - self.RemoveRedundantZeros(text_format.MessageToString(message)), - 'repeated_int64: -9223372036854775808\n' - 'repeated_uint64: 18446744073709551615\n' - 'repeated_double: 123.456\n' - 'repeated_double: 1.23e+22\n' - 'repeated_double: 1.23e-18\n' - 'repeated_string: ' - '\"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\\"\"\n') + text_format.MessageToString(message, as_one_line=True), + 'repeated_int32: 1 repeated_int32: 1 repeated_int32: 3 ' + 'repeated_string: "Google" repeated_string: "Zurich"') + + def testPrintNestedNewLineInStringAsOneLine(self): + message = unittest_pb2.TestAllTypes() + message.optional_string = "a\nnew\nline" + self.CompareToGoldenText( + text_format.MessageToString(message, as_one_line=True), + 'optional_string: "a\\nnew\\nline"') + + def testPrintMessageSetAsOneLine(self): + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + self.CompareToGoldenText( + text_format.MessageToString(message, as_one_line=True), + 'message_set {' + ' [protobuf_unittest.TestMessageSetExtension1] {' + ' i: 23' + ' }' + ' [protobuf_unittest.TestMessageSetExtension2] {' + ' str: \"foo\"' + ' }' + ' }') + + def testPrintExoticAsOneLine(self): + message = unittest_pb2.TestAllTypes() + message.repeated_int64.append(-9223372036854775808) + message.repeated_uint64.append(18446744073709551615) + message.repeated_double.append(123.456) + message.repeated_double.append(1.23e22) + message.repeated_double.append(1.23e-18) + message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"') + message.repeated_string.append(u'\u00fc\ua71f') + self.CompareToGoldenText( + self.RemoveRedundantZeros( + text_format.MessageToString(message, as_one_line=True)), + 'repeated_int64: -9223372036854775808' + ' repeated_uint64: 18446744073709551615' + ' repeated_double: 123.456' + ' repeated_double: 1.23e+22' + ' repeated_double: 1.23e-18' + ' repeated_string: ' + '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""' + ' repeated_string: "\\303\\274\\352\\234\\237"') + + def testRoundTripExoticAsOneLine(self): + message = unittest_pb2.TestAllTypes() + message.repeated_int64.append(-9223372036854775808) + message.repeated_uint64.append(18446744073709551615) + message.repeated_double.append(123.456) + message.repeated_double.append(1.23e22) + message.repeated_double.append(1.23e-18) + message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"') + message.repeated_string.append(u'\u00fc\ua71f') + + # Test as_utf8 = False. + wire_text = text_format.MessageToString( + message, as_one_line=True, as_utf8=False) + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.Parse(wire_text, parsed_message) + self.assertIs(r, parsed_message) + self.assertEquals(message, parsed_message) + + # Test as_utf8 = True. + wire_text = text_format.MessageToString( + message, as_one_line=True, as_utf8=True) + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.Parse(wire_text, parsed_message) + self.assertIs(r, parsed_message) + self.assertEquals(message, parsed_message, + '\n%s != %s' % (message, parsed_message)) + + def testPrintRawUtf8String(self): + message = unittest_pb2.TestAllTypes() + message.repeated_string.append(u'\u00fc\ua71f') + text = text_format.MessageToString(message, as_utf8=True) + self.CompareToGoldenText(text, 'repeated_string: "\303\274\352\234\237"\n') + parsed_message = unittest_pb2.TestAllTypes() + text_format.Parse(text, parsed_message) + self.assertEquals(message, parsed_message, + '\n%s != %s' % (message, parsed_message)) + + def testPrintFloatFormat(self): + # Check that float_format argument is passed to sub-message formatting. + message = unittest_pb2.NestedTestAllTypes() + # We use 1.25 as it is a round number in binary. The proto 32-bit float + # will not gain additional imprecise digits as a 64-bit Python float and + # show up in its str. 32-bit 1.2 is noisy when extended to 64-bit: + # >>> struct.unpack('f', struct.pack('f', 1.2))[0] + # 1.2000000476837158 + # >>> struct.unpack('f', struct.pack('f', 1.25))[0] + # 1.25 + message.payload.optional_float = 1.25 + # Check rounding at 15 significant digits + message.payload.optional_double = -.000003456789012345678 + # Check no decimal point. + message.payload.repeated_float.append(-5642) + # Check no trailing zeros. + message.payload.repeated_double.append(.000078900) + formatted_fields = ['optional_float: 1.25', + 'optional_double: -3.45678901234568e-6', + 'repeated_float: -5642', + 'repeated_double: 7.89e-5'] + text_message = text_format.MessageToString(message, float_format='.15g') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_message), + 'payload {{\n {}\n {}\n {}\n {}\n}}\n'.format(*formatted_fields)) + # as_one_line=True is a separate code branch where float_format is passed. + text_message = text_format.MessageToString(message, as_one_line=True, + float_format='.15g') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_message), + 'payload {{ {} {} {} {} }}'.format(*formatted_fields)) def testMessageToString(self): message = unittest_pb2.ForeignMessage() @@ -119,52 +288,57 @@ class TextFormatTest(unittest.TestCase): def RemoveRedundantZeros(self, text): # Some platforms print 1e+5 as 1e+005. This is fine, but we need to remove # these zeros in order to match the golden file. - return text.replace('e+0','e+').replace('e+0','e+') \ + text = text.replace('e+0','e+').replace('e+0','e+') \ .replace('e-0','e-').replace('e-0','e-') + # Floating point fields are printed with .0 suffix even if they are + # actualy integer numbers. + text = re.compile('\.0$', re.MULTILINE).sub('', text) + return text - def testMergeGolden(self): + def testParseGolden(self): golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt')) parsed_message = unittest_pb2.TestAllTypes() - text_format.Merge(golden_text, parsed_message) + r = text_format.Parse(golden_text, parsed_message) + self.assertIs(r, parsed_message) message = unittest_pb2.TestAllTypes() test_util.SetAllFields(message) self.assertEquals(message, parsed_message) - def testMergeGoldenExtensions(self): + def testParseGoldenExtensions(self): golden_text = '\n'.join(self.ReadGolden( 'text_format_unittest_extensions_data.txt')) parsed_message = unittest_pb2.TestAllExtensions() - text_format.Merge(golden_text, parsed_message) + text_format.Parse(golden_text, parsed_message) message = unittest_pb2.TestAllExtensions() test_util.SetAllExtensions(message) self.assertEquals(message, parsed_message) - def testMergeAllFields(self): + def testParseAllFields(self): message = unittest_pb2.TestAllTypes() test_util.SetAllFields(message) ascii_text = text_format.MessageToString(message) parsed_message = unittest_pb2.TestAllTypes() - text_format.Merge(ascii_text, parsed_message) + text_format.Parse(ascii_text, parsed_message) self.assertEqual(message, parsed_message) test_util.ExpectAllFieldsSet(self, message) - def testMergeAllExtensions(self): + def testParseAllExtensions(self): message = unittest_pb2.TestAllExtensions() test_util.SetAllExtensions(message) ascii_text = text_format.MessageToString(message) parsed_message = unittest_pb2.TestAllExtensions() - text_format.Merge(ascii_text, parsed_message) + text_format.Parse(ascii_text, parsed_message) self.assertEqual(message, parsed_message) - def testMergeMessageSet(self): + def testParseMessageSet(self): message = unittest_pb2.TestAllTypes() text = ('repeated_uint64: 1\n' 'repeated_uint64: 2\n') - text_format.Merge(text, message) + text_format.Parse(text, message) self.assertEqual(1, message.repeated_uint64[0]) self.assertEqual(2, message.repeated_uint64[1]) @@ -177,13 +351,13 @@ class TextFormatTest(unittest.TestCase): ' str: \"foo\"\n' ' }\n' '}\n') - text_format.Merge(text, message) + text_format.Parse(text, message) ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension self.assertEquals(23, message.message_set.Extensions[ext1].i) self.assertEquals('foo', message.message_set.Extensions[ext2].str) - def testMergeExotic(self): + def testParseExotic(self): message = unittest_pb2.TestAllTypes() text = ('repeated_int64: -9223372036854775808\n' 'repeated_uint64: 18446744073709551615\n' @@ -191,9 +365,12 @@ class TextFormatTest(unittest.TestCase): 'repeated_double: 1.23e+22\n' 'repeated_double: 1.23e-18\n' 'repeated_string: \n' - '\"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\\"\"\n' - 'repeated_string: "foo" \'corge\' "grault"') - text_format.Merge(text, message) + '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n' + 'repeated_string: "foo" \'corge\' "grault"\n' + 'repeated_string: "\\303\\274\\352\\234\\237"\n' + 'repeated_string: "\\xc3\\xbc"\n' + 'repeated_string: "\xc3\xbc"\n') + text_format.Parse(text, message) self.assertEqual(-9223372036854775808, message.repeated_int64[0]) self.assertEqual(18446744073709551615, message.repeated_uint64[0]) @@ -201,95 +378,217 @@ class TextFormatTest(unittest.TestCase): self.assertEqual(1.23e22, message.repeated_double[1]) self.assertEqual(1.23e-18, message.repeated_double[2]) self.assertEqual( - '\000\001\a\b\f\n\r\t\v\\\'\"', message.repeated_string[0]) + '\000\001\a\b\f\n\r\t\v\\\'"', message.repeated_string[0]) self.assertEqual('foocorgegrault', message.repeated_string[1]) + self.assertEqual(u'\u00fc\ua71f', message.repeated_string[2]) + self.assertEqual(u'\u00fc', message.repeated_string[3]) + + def testParseTrailingCommas(self): + message = unittest_pb2.TestAllTypes() + text = ('repeated_int64: 100;\n' + 'repeated_int64: 200;\n' + 'repeated_int64: 300,\n' + 'repeated_string: "one",\n' + 'repeated_string: "two";\n') + text_format.Parse(text, message) + + self.assertEqual(100, message.repeated_int64[0]) + self.assertEqual(200, message.repeated_int64[1]) + self.assertEqual(300, message.repeated_int64[2]) + self.assertEqual(u'one', message.repeated_string[0]) + self.assertEqual(u'two', message.repeated_string[1]) + + def testParseEmptyText(self): + message = unittest_pb2.TestAllTypes() + text = '' + text_format.Parse(text, message) + self.assertEquals(unittest_pb2.TestAllTypes(), message) + + def testParseInvalidUtf8(self): + message = unittest_pb2.TestAllTypes() + text = 'repeated_string: "\\xc3\\xc3"' + self.assertRaises(text_format.ParseError, text_format.Parse, text, message) + + def testParseSingleWord(self): + message = unittest_pb2.TestAllTypes() + text = 'foo' + self.assertRaisesWithLiteralMatch( + text_format.ParseError, + ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named ' + '"foo".'), + text_format.Parse, text, message) - def testMergeUnknownField(self): + def testParseUnknownField(self): message = unittest_pb2.TestAllTypes() text = 'unknown_field: 8\n' - self.assertRaisesWithMessage( + self.assertRaisesWithLiteralMatch( text_format.ParseError, ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named ' '"unknown_field".'), - text_format.Merge, text, message) + text_format.Parse, text, message) - def testMergeBadExtension(self): + def testParseBadExtension(self): message = unittest_pb2.TestAllExtensions() text = '[unknown_extension]: 8\n' - self.assertRaisesWithMessage( + self.assertRaisesWithLiteralMatch( text_format.ParseError, '1:2 : Extension "unknown_extension" not registered.', - text_format.Merge, text, message) + text_format.Parse, text, message) message = unittest_pb2.TestAllTypes() - self.assertRaisesWithMessage( + self.assertRaisesWithLiteralMatch( text_format.ParseError, ('1:2 : Message type "protobuf_unittest.TestAllTypes" does not have ' 'extensions.'), - text_format.Merge, text, message) + text_format.Parse, text, message) - def testMergeGroupNotClosed(self): + def testParseGroupNotClosed(self): message = unittest_pb2.TestAllTypes() text = 'RepeatedGroup: <' - self.assertRaisesWithMessage( + self.assertRaisesWithLiteralMatch( text_format.ParseError, '1:16 : Expected ">".', - text_format.Merge, text, message) + text_format.Parse, text, message) text = 'RepeatedGroup: {' - self.assertRaisesWithMessage( + self.assertRaisesWithLiteralMatch( text_format.ParseError, '1:16 : Expected "}".', - text_format.Merge, text, message) + text_format.Parse, text, message) - def testMergeEmptyGroup(self): + def testParseEmptyGroup(self): message = unittest_pb2.TestAllTypes() text = 'OptionalGroup: {}' - text_format.Merge(text, message) + text_format.Parse(text, message) self.assertTrue(message.HasField('optionalgroup')) message.Clear() message = unittest_pb2.TestAllTypes() text = 'OptionalGroup: <>' - text_format.Merge(text, message) + text_format.Parse(text, message) self.assertTrue(message.HasField('optionalgroup')) - def testMergeBadEnumValue(self): + def testParseBadEnumValue(self): message = unittest_pb2.TestAllTypes() text = 'optional_nested_enum: BARR' - self.assertRaisesWithMessage( + self.assertRaisesWithLiteralMatch( text_format.ParseError, ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" ' 'has no value named BARR.'), - text_format.Merge, text, message) + text_format.Parse, text, message) message = unittest_pb2.TestAllTypes() text = 'optional_nested_enum: 100' - self.assertRaisesWithMessage( + self.assertRaisesWithLiteralMatch( text_format.ParseError, ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" ' 'has no value with number 100.'), - text_format.Merge, text, message) - - def assertRaisesWithMessage(self, e_class, e, func, *args, **kwargs): - """Same as assertRaises, but also compares the exception message.""" - if hasattr(e_class, '__name__'): - exc_name = e_class.__name__ - else: - exc_name = str(e_class) - - try: - func(*args, **kwargs) - except e_class, expr: - if str(expr) != e: - msg = '%s raised, but with wrong message: "%s" instead of "%s"' - raise self.failureException(msg % (exc_name, - str(expr).encode('string_escape'), - e.encode('string_escape'))) - return - else: - raise self.failureException('%s not raised' % exc_name) - - -class TokenizerTest(unittest.TestCase): + text_format.Parse, text, message) + + def testParseBadIntValue(self): + message = unittest_pb2.TestAllTypes() + text = 'optional_int32: bork' + self.assertRaisesWithLiteralMatch( + text_format.ParseError, + ('1:17 : Couldn\'t parse integer: bork'), + text_format.Parse, text, message) + + def testParseStringFieldUnescape(self): + message = unittest_pb2.TestAllTypes() + text = r'''repeated_string: "\xf\x62" + repeated_string: "\\xf\\x62" + repeated_string: "\\\xf\\\x62" + repeated_string: "\\\\xf\\\\x62" + repeated_string: "\\\\\xf\\\\\x62" + repeated_string: "\x5cx20"''' + text_format.Parse(text, message) + + SLASH = '\\' + self.assertEqual('\x0fb', message.repeated_string[0]) + self.assertEqual(SLASH + 'xf' + SLASH + 'x62', message.repeated_string[1]) + self.assertEqual(SLASH + '\x0f' + SLASH + 'b', message.repeated_string[2]) + self.assertEqual(SLASH + SLASH + 'xf' + SLASH + SLASH + 'x62', + message.repeated_string[3]) + self.assertEqual(SLASH + SLASH + '\x0f' + SLASH + SLASH + 'b', + message.repeated_string[4]) + self.assertEqual(SLASH + 'x20', message.repeated_string[5]) + + def testMergeRepeatedScalars(self): + message = unittest_pb2.TestAllTypes() + text = ('optional_int32: 42 ' + 'optional_int32: 67') + r = text_format.Merge(text, message) + self.assertIs(r, message) + self.assertEqual(67, message.optional_int32) + + def testParseRepeatedScalars(self): + message = unittest_pb2.TestAllTypes() + text = ('optional_int32: 42 ' + 'optional_int32: 67') + self.assertRaisesWithLiteralMatch( + text_format.ParseError, + ('1:36 : Message type "protobuf_unittest.TestAllTypes" should not ' + 'have multiple "optional_int32" fields.'), + text_format.Parse, text, message) + + def testMergeRepeatedNestedMessageScalars(self): + message = unittest_pb2.TestAllTypes() + text = ('optional_nested_message { bb: 1 } ' + 'optional_nested_message { bb: 2 }') + r = text_format.Merge(text, message) + self.assertTrue(r is message) + self.assertEqual(2, message.optional_nested_message.bb) + + def testParseRepeatedNestedMessageScalars(self): + message = unittest_pb2.TestAllTypes() + text = ('optional_nested_message { bb: 1 } ' + 'optional_nested_message { bb: 2 }') + self.assertRaisesWithLiteralMatch( + text_format.ParseError, + ('1:65 : Message type "protobuf_unittest.TestAllTypes.NestedMessage" ' + 'should not have multiple "bb" fields.'), + text_format.Parse, text, message) + + def testMergeRepeatedExtensionScalars(self): + message = unittest_pb2.TestAllExtensions() + text = ('[protobuf_unittest.optional_int32_extension]: 42 ' + '[protobuf_unittest.optional_int32_extension]: 67') + text_format.Merge(text, message) + self.assertEqual( + 67, + message.Extensions[unittest_pb2.optional_int32_extension]) + + def testParseRepeatedExtensionScalars(self): + message = unittest_pb2.TestAllExtensions() + text = ('[protobuf_unittest.optional_int32_extension]: 42 ' + '[protobuf_unittest.optional_int32_extension]: 67') + self.assertRaisesWithLiteralMatch( + text_format.ParseError, + ('1:96 : Message type "protobuf_unittest.TestAllExtensions" ' + 'should not have multiple ' + '"protobuf_unittest.optional_int32_extension" extensions.'), + text_format.Parse, text, message) + + def testParseLinesGolden(self): + opened = self.ReadGolden('text_format_unittest_data.txt') + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.ParseLines(opened, parsed_message) + self.assertIs(r, parsed_message) + + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.assertEquals(message, parsed_message) + + def testMergeLinesGolden(self): + opened = self.ReadGolden('text_format_unittest_data.txt') + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.MergeLines(opened, parsed_message) + self.assertIs(r, parsed_message) + + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.assertEqual(message, parsed_message) + + +class TokenizerTest(basetest.TestCase): def testSimpleTokenCases(self): text = ('identifier1:"string1"\n \n\n' @@ -297,8 +596,9 @@ class TokenizerTest(unittest.TestCase): 'identifiER_4 : 1.1e+2 ID5:-0.23 ID6:\'aaaa\\\'bbbb\'\n' 'ID7 : "aa\\"bb"\n\n\n\n ID8: {A:inf B:-inf C:true D:false}\n' 'ID9: 22 ID10: -111111111111111111 ID11: -22\n' - 'ID12: 2222222222222222222') - tokenizer = text_format._Tokenizer(text) + 'ID12: 2222222222222222222 ID13: 1.23456f ID14: 1.2e+2f ' + 'false_bool: 0 true_BOOL:t \n true_bool1: 1 false_BOOL1:f ') + tokenizer = text_format._Tokenizer(text.splitlines()) methods = [(tokenizer.ConsumeIdentifier, 'identifier1'), ':', (tokenizer.ConsumeString, 'string1'), @@ -325,10 +625,10 @@ class TokenizerTest(unittest.TestCase): '{', (tokenizer.ConsumeIdentifier, 'A'), ':', - (tokenizer.ConsumeFloat, text_format._INFINITY), + (tokenizer.ConsumeFloat, float('inf')), (tokenizer.ConsumeIdentifier, 'B'), ':', - (tokenizer.ConsumeFloat, -text_format._INFINITY), + (tokenizer.ConsumeFloat, -float('inf')), (tokenizer.ConsumeIdentifier, 'C'), ':', (tokenizer.ConsumeBool, True), @@ -347,7 +647,25 @@ class TokenizerTest(unittest.TestCase): (tokenizer.ConsumeInt32, -22), (tokenizer.ConsumeIdentifier, 'ID12'), ':', - (tokenizer.ConsumeUint64, 2222222222222222222)] + (tokenizer.ConsumeUint64, 2222222222222222222), + (tokenizer.ConsumeIdentifier, 'ID13'), + ':', + (tokenizer.ConsumeFloat, 1.23456), + (tokenizer.ConsumeIdentifier, 'ID14'), + ':', + (tokenizer.ConsumeFloat, 1.2e+2), + (tokenizer.ConsumeIdentifier, 'false_bool'), + ':', + (tokenizer.ConsumeBool, False), + (tokenizer.ConsumeIdentifier, 'true_BOOL'), + ':', + (tokenizer.ConsumeBool, True), + (tokenizer.ConsumeIdentifier, 'true_bool1'), + ':', + (tokenizer.ConsumeBool, True), + (tokenizer.ConsumeIdentifier, 'false_BOOL1'), + ':', + (tokenizer.ConsumeBool, False)] i = 0 while not tokenizer.AtEnd(): @@ -366,7 +684,7 @@ class TokenizerTest(unittest.TestCase): int64_max = (1 << 63) - 1 uint32_max = (1 << 32) - 1 text = '-1 %d %d' % (uint32_max + 1, int64_max + 1) - tokenizer = text_format._Tokenizer(text) + tokenizer = text_format._Tokenizer(text.splitlines()) self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32) self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint64) self.assertEqual(-1, tokenizer.ConsumeInt32()) @@ -380,7 +698,7 @@ class TokenizerTest(unittest.TestCase): self.assertTrue(tokenizer.AtEnd()) text = '-0 -0 0 0' - tokenizer = text_format._Tokenizer(text) + tokenizer = text_format._Tokenizer(text.splitlines()) self.assertEqual(0, tokenizer.ConsumeUint32()) self.assertEqual(0, tokenizer.ConsumeUint64()) self.assertEqual(0, tokenizer.ConsumeUint32()) @@ -389,40 +707,30 @@ class TokenizerTest(unittest.TestCase): def testConsumeByteString(self): text = '"string1\'' - tokenizer = text_format._Tokenizer(text) + tokenizer = text_format._Tokenizer(text.splitlines()) self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) text = 'string1"' - tokenizer = text_format._Tokenizer(text) + tokenizer = text_format._Tokenizer(text.splitlines()) self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) text = '\n"\\xt"' - tokenizer = text_format._Tokenizer(text) + tokenizer = text_format._Tokenizer(text.splitlines()) self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) text = '\n"\\"' - tokenizer = text_format._Tokenizer(text) + tokenizer = text_format._Tokenizer(text.splitlines()) self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) text = '\n"\\x"' - tokenizer = text_format._Tokenizer(text) + tokenizer = text_format._Tokenizer(text.splitlines()) self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) def testConsumeBool(self): text = 'not-a-bool' - tokenizer = text_format._Tokenizer(text) + tokenizer = text_format._Tokenizer(text.splitlines()) self.assertRaises(text_format.ParseError, tokenizer.ConsumeBool) - def testInfNan(self): - # Make sure our infinity and NaN definitions are sound. - self.assertEquals(float, type(text_format._INFINITY)) - self.assertEquals(float, type(text_format._NAN)) - self.assertTrue(text_format._NAN != text_format._NAN) - - inf_times_zero = text_format._INFINITY * 0 - self.assertTrue(inf_times_zero != inf_times_zero) - self.assertTrue(text_format._INFINITY > 0) - if __name__ == '__main__': - unittest.main() + basetest.main() diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py index 2b3cd4d..8e1b3cc 100755 --- a/python/google/protobuf/internal/type_checkers.py +++ b/python/google/protobuf/internal/type_checkers.py @@ -28,6 +28,10 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#PY25 compatible for GAE. +# +# Copyright 2008 Google Inc. All Rights Reserved. + """Provides type checking routines. This module defines type checking utilities in the forms of dictionaries: @@ -45,6 +49,9 @@ TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization __author__ = 'robinson@google.com (Will Robinson)' +import sys ##PY25 +if sys.version < '2.6': bytes = str ##PY25 +from google.protobuf.internal import api_implementation from google.protobuf.internal import decoder from google.protobuf.internal import encoder from google.protobuf.internal import wire_format @@ -53,21 +60,22 @@ from google.protobuf import descriptor _FieldDescriptor = descriptor.FieldDescriptor -def GetTypeChecker(cpp_type, field_type): +def GetTypeChecker(field): """Returns a type checker for a message field of the specified types. Args: - cpp_type: C++ type of the field (see descriptor.py). - field_type: Protocol message field type (see descriptor.py). + field: FieldDescriptor object for this field. Returns: An instance of TypeChecker which can be used to verify the types of values assigned to a field of the specified type. """ - if (cpp_type == _FieldDescriptor.CPPTYPE_STRING and - field_type == _FieldDescriptor.TYPE_STRING): + if (field.cpp_type == _FieldDescriptor.CPPTYPE_STRING and + field.type == _FieldDescriptor.TYPE_STRING): return UnicodeValueChecker() - return _VALUE_CHECKERS[cpp_type] + if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: + return EnumValueChecker(field.enum_type) + return _VALUE_CHECKERS[field.cpp_type] # None of the typecheckers below make any attempt to guard against people @@ -85,10 +93,15 @@ class TypeChecker(object): self._acceptable_types = acceptable_types def CheckValue(self, proposed_value): + """Type check the provided value and return it. + + The returned value might have been normalized to another type. + """ if not isinstance(proposed_value, self._acceptable_types): message = ('%.1024r has type %s, but expected one of: %s' % (proposed_value, type(proposed_value), self._acceptable_types)) raise TypeError(message) + return proposed_value # IntValueChecker and its subclasses perform integer type-checks @@ -104,28 +117,54 @@ class IntValueChecker(object): raise TypeError(message) if not self._MIN <= proposed_value <= self._MAX: raise ValueError('Value out of range: %d' % proposed_value) + # We force 32-bit values to int and 64-bit values to long to make + # alternate implementations where the distinction is more significant + # (e.g. the C++ implementation) simpler. + proposed_value = self._TYPE(proposed_value) + return proposed_value + + +class EnumValueChecker(object): + + """Checker used for enum fields. Performs type-check and range check.""" + + def __init__(self, enum_type): + self._enum_type = enum_type + + def CheckValue(self, proposed_value): + if not isinstance(proposed_value, (int, long)): + message = ('%.1024r has type %s, but expected one of: %s' % + (proposed_value, type(proposed_value), (int, long))) + raise TypeError(message) + if proposed_value not in self._enum_type.values_by_number: + raise ValueError('Unknown enum value: %d' % proposed_value) + return proposed_value class UnicodeValueChecker(object): - """Checker used for string fields.""" + """Checker used for string fields. + + Always returns a unicode value, even if the input is of type str. + """ def CheckValue(self, proposed_value): - if not isinstance(proposed_value, (str, unicode)): + if not isinstance(proposed_value, (bytes, unicode)): message = ('%.1024r has type %s, but expected one of: %s' % - (proposed_value, type(proposed_value), (str, unicode))) + (proposed_value, type(proposed_value), (bytes, unicode))) raise TypeError(message) - # If the value is of type 'str' make sure that it is in 7-bit ASCII + # If the value is of type 'bytes' make sure that it is in 7-bit ASCII # encoding. - if isinstance(proposed_value, str): + if isinstance(proposed_value, bytes): try: - unicode(proposed_value, 'ascii') + proposed_value = proposed_value.decode('ascii') except UnicodeDecodeError: - raise ValueError('%.1024r has type str, but isn\'t in 7-bit ASCII ' + raise ValueError('%.1024r has type bytes, but isn\'t in 7-bit ASCII ' 'encoding. Non-ASCII strings must be converted to ' 'unicode objects before being added.' % (proposed_value)) + return proposed_value class Int32ValueChecker(IntValueChecker): @@ -133,21 +172,25 @@ class Int32ValueChecker(IntValueChecker): # efficient. _MIN = -2147483648 _MAX = 2147483647 + _TYPE = int class Uint32ValueChecker(IntValueChecker): _MIN = 0 _MAX = (1 << 32) - 1 + _TYPE = int class Int64ValueChecker(IntValueChecker): _MIN = -(1 << 63) _MAX = (1 << 63) - 1 + _TYPE = long class Uint64ValueChecker(IntValueChecker): _MIN = 0 _MAX = (1 << 64) - 1 + _TYPE = long # Type-checkers for all scalar CPPTYPEs. @@ -161,8 +204,7 @@ _VALUE_CHECKERS = { _FieldDescriptor.CPPTYPE_FLOAT: TypeChecker( float, int, long), _FieldDescriptor.CPPTYPE_BOOL: TypeChecker(bool, int), - _FieldDescriptor.CPPTYPE_ENUM: Int32ValueChecker(), - _FieldDescriptor.CPPTYPE_STRING: TypeChecker(str), + _FieldDescriptor.CPPTYPE_STRING: TypeChecker(bytes), } diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py new file mode 100755 index 0000000..8f3354c --- /dev/null +++ b/python/google/protobuf/internal/unknown_fields_test.py @@ -0,0 +1,231 @@ +#! /usr/bin/python +# -*- coding: utf-8 -*- +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Test for preservation of unknown fields in the pure Python implementation.""" + +__author__ = 'bohdank@google.com (Bohdan Koval)' + +from google.apputils import basetest +from google.protobuf import unittest_mset_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf.internal import encoder +from google.protobuf.internal import missing_enum_values_pb2 +from google.protobuf.internal import test_util +from google.protobuf.internal import type_checkers + + +class UnknownFieldsTest(basetest.TestCase): + + def setUp(self): + self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + self.all_fields = unittest_pb2.TestAllTypes() + test_util.SetAllFields(self.all_fields) + self.all_fields_data = self.all_fields.SerializeToString() + self.empty_message = unittest_pb2.TestEmptyMessage() + self.empty_message.ParseFromString(self.all_fields_data) + self.unknown_fields = self.empty_message._unknown_fields + + def GetField(self, name): + field_descriptor = self.descriptor.fields_by_name[name] + wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type] + field_tag = encoder.TagBytes(field_descriptor.number, wire_type) + result_dict = {} + for tag_bytes, value in self.unknown_fields: + if tag_bytes == field_tag: + decoder = unittest_pb2.TestAllTypes._decoders_by_tag[tag_bytes] + decoder(value, 0, len(value), self.all_fields, result_dict) + return result_dict[field_descriptor] + + def testEnum(self): + value = self.GetField('optional_nested_enum') + self.assertEqual(self.all_fields.optional_nested_enum, value) + + def testRepeatedEnum(self): + value = self.GetField('repeated_nested_enum') + self.assertEqual(self.all_fields.repeated_nested_enum, value) + + def testVarint(self): + value = self.GetField('optional_int32') + self.assertEqual(self.all_fields.optional_int32, value) + + def testFixed32(self): + value = self.GetField('optional_fixed32') + self.assertEqual(self.all_fields.optional_fixed32, value) + + def testFixed64(self): + value = self.GetField('optional_fixed64') + self.assertEqual(self.all_fields.optional_fixed64, value) + + def testLengthDelimited(self): + value = self.GetField('optional_string') + self.assertEqual(self.all_fields.optional_string, value) + + def testGroup(self): + value = self.GetField('optionalgroup') + self.assertEqual(self.all_fields.optionalgroup, value) + + def testSerialize(self): + data = self.empty_message.SerializeToString() + + # Don't use assertEqual because we don't want to dump raw binary data to + # stdout. + self.assertTrue(data == self.all_fields_data) + + def testCopyFrom(self): + message = unittest_pb2.TestEmptyMessage() + message.CopyFrom(self.empty_message) + self.assertEqual(self.unknown_fields, message._unknown_fields) + + def testMergeFrom(self): + message = unittest_pb2.TestAllTypes() + message.optional_int32 = 1 + message.optional_uint32 = 2 + source = unittest_pb2.TestEmptyMessage() + source.ParseFromString(message.SerializeToString()) + + message.ClearField('optional_int32') + message.optional_int64 = 3 + message.optional_uint32 = 4 + destination = unittest_pb2.TestEmptyMessage() + destination.ParseFromString(message.SerializeToString()) + unknown_fields = destination._unknown_fields[:] + + destination.MergeFrom(source) + self.assertEqual(unknown_fields + source._unknown_fields, + destination._unknown_fields) + + def testClear(self): + self.empty_message.Clear() + self.assertEqual(0, len(self.empty_message._unknown_fields)) + + def testByteSize(self): + self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize()) + + def testUnknownExtensions(self): + message = unittest_pb2.TestEmptyMessageWithExtensions() + message.ParseFromString(self.all_fields_data) + self.assertEqual(self.empty_message._unknown_fields, + message._unknown_fields) + + def testListFields(self): + # Make sure ListFields doesn't return unknown fields. + self.assertEqual(0, len(self.empty_message.ListFields())) + + def testSerializeMessageSetWireFormatUnknownExtension(self): + # Create a message using the message set wire format with an unknown + # message. + raw = unittest_mset_pb2.RawMessageSet() + + # Add an unknown extension. + item = raw.item.add() + item.type_id = 1545009 + message1 = unittest_mset_pb2.TestMessageSetExtension1() + message1.i = 12345 + item.message = message1.SerializeToString() + + serialized = raw.SerializeToString() + + # Parse message using the message set wire format. + proto = unittest_mset_pb2.TestMessageSet() + proto.MergeFromString(serialized) + + # Verify that the unknown extension is serialized unchanged + reserialized = proto.SerializeToString() + new_raw = unittest_mset_pb2.RawMessageSet() + new_raw.MergeFromString(reserialized) + self.assertEqual(raw, new_raw) + + def testEquals(self): + message = unittest_pb2.TestEmptyMessage() + message.ParseFromString(self.all_fields_data) + self.assertEqual(self.empty_message, message) + + self.all_fields.ClearField('optional_string') + message.ParseFromString(self.all_fields.SerializeToString()) + self.assertNotEqual(self.empty_message, message) + + +class UnknownFieldsTest(basetest.TestCase): + + def setUp(self): + self.descriptor = missing_enum_values_pb2.TestEnumValues.DESCRIPTOR + + self.message = missing_enum_values_pb2.TestEnumValues() + self.message.optional_nested_enum = ( + missing_enum_values_pb2.TestEnumValues.ZERO) + self.message.repeated_nested_enum.extend([ + missing_enum_values_pb2.TestEnumValues.ZERO, + missing_enum_values_pb2.TestEnumValues.ONE, + ]) + self.message.packed_nested_enum.extend([ + missing_enum_values_pb2.TestEnumValues.ZERO, + missing_enum_values_pb2.TestEnumValues.ONE, + ]) + self.message_data = self.message.SerializeToString() + self.missing_message = missing_enum_values_pb2.TestMissingEnumValues() + self.missing_message.ParseFromString(self.message_data) + self.unknown_fields = self.missing_message._unknown_fields + + def GetField(self, name): + field_descriptor = self.descriptor.fields_by_name[name] + wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type] + field_tag = encoder.TagBytes(field_descriptor.number, wire_type) + result_dict = {} + for tag_bytes, value in self.unknown_fields: + if tag_bytes == field_tag: + decoder = missing_enum_values_pb2.TestEnumValues._decoders_by_tag[ + tag_bytes] + decoder(value, 0, len(value), self.message, result_dict) + return result_dict[field_descriptor] + + def testUnknownEnumValue(self): + self.assertFalse(self.missing_message.HasField('optional_nested_enum')) + value = self.GetField('optional_nested_enum') + self.assertEqual(self.message.optional_nested_enum, value) + + def testUnknownRepeatedEnumValue(self): + value = self.GetField('repeated_nested_enum') + self.assertEqual(self.message.repeated_nested_enum, value) + + def testUnknownPackedEnumValue(self): + value = self.GetField('packed_nested_enum') + self.assertEqual(self.message.packed_nested_enum, value) + + def testRoundTrip(self): + new_message = missing_enum_values_pb2.TestEnumValues() + new_message.ParseFromString(self.missing_message.SerializeToString()) + self.assertEqual(self.message, new_message) + + +if __name__ == '__main__': + basetest.main() diff --git a/python/google/protobuf/internal/wire_format_test.py b/python/google/protobuf/internal/wire_format_test.py index 7600778..9362c72 100755 --- a/python/google/protobuf/internal/wire_format_test.py +++ b/python/google/protobuf/internal/wire_format_test.py @@ -34,12 +34,12 @@ __author__ = 'robinson@google.com (Will Robinson)' -import unittest +from google.apputils import basetest from google.protobuf import message from google.protobuf.internal import wire_format -class WireFormatTest(unittest.TestCase): +class WireFormatTest(basetest.TestCase): def testPackTag(self): field_number = 0xabc @@ -195,7 +195,7 @@ class WireFormatTest(unittest.TestCase): # Test UTF-8 string byte size calculation. # 1 byte for tag, 1 byte for length, 8 bytes for content. self.assertEqual(10, wire_format.StringByteSize( - 5, unicode('\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82', 'utf-8'))) + 5, b'\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82'.decode('utf-8'))) class MockMessage(object): def __init__(self, byte_size): @@ -250,4 +250,4 @@ class WireFormatTest(unittest.TestCase): if __name__ == '__main__': - unittest.main() + basetest.main() diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py index f839847..37b0af1 100755 --- a/python/google/protobuf/message.py +++ b/python/google/protobuf/message.py @@ -67,14 +67,28 @@ class Message(object): DESCRIPTOR = None + def __deepcopy__(self, memo=None): + clone = type(self)() + clone.MergeFrom(self) + return clone + def __eq__(self, other_msg): + """Recursively compares two messages by value and structure.""" raise NotImplementedError def __ne__(self, other_msg): # Can't just say self != other_msg, since that would infinitely recurse. :) return not self == other_msg + def __hash__(self): + raise TypeError('unhashable object') + def __str__(self): + """Outputs a human-readable representation of the message.""" + raise NotImplementedError + + def __unicode__(self): + """Outputs a human-readable representation of the message.""" raise NotImplementedError def MergeFrom(self, other_msg): @@ -163,7 +177,11 @@ class Message(object): raise NotImplementedError def ParseFromString(self, serialized): - """Like MergeFromString(), except we clear the object first.""" + """Parse serialized protocol buffer data into this message. + + Like MergeFromString(), except we clear the object first and + do not return the value that MergeFromString returns. + """ self.Clear() self.MergeFromString(serialized) @@ -215,6 +233,9 @@ class Message(object): raise NotImplementedError def HasField(self, field_name): + """Checks if a certain field is set for the message. Note if the + field_name is not defined in the message descriptor, ValueError will be + raised.""" raise NotImplementedError def ClearField(self, field_name): @@ -252,3 +273,12 @@ class Message(object): via a previous _SetListener() call. """ raise NotImplementedError + + def __getstate__(self): + """Support the pickle protocol.""" + return dict(serialized=self.SerializePartialToString()) + + def __setstate__(self, state): + """Support the pickle protocol.""" + self.__init__() + self.ParseFromString(state['serialized']) diff --git a/python/google/protobuf/message_factory.py b/python/google/protobuf/message_factory.py new file mode 100644 index 0000000..9004ffd --- /dev/null +++ b/python/google/protobuf/message_factory.py @@ -0,0 +1,155 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +#PY25 compatible for GAE. +# +# Copyright 2012 Google Inc. All Rights Reserved. + +"""Provides a factory class for generating dynamic messages. + +The easiest way to use this class is if you have access to the FileDescriptor +protos containing the messages you want to create you can just do the following: + +message_classes = message_factory.GetMessages(iterable_of_file_descriptors) +my_proto_instance = message_classes['some.proto.package.MessageName']() +""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +import sys ##PY25 +from google.protobuf import descriptor_database +from google.protobuf import descriptor_pool +from google.protobuf import message +from google.protobuf import reflection + + +class MessageFactory(object): + """Factory for creating Proto2 messages from descriptors in a pool.""" + + def __init__(self, pool=None): + """Initializes a new factory.""" + self.pool = (pool or descriptor_pool.DescriptorPool( + descriptor_database.DescriptorDatabase())) + + # local cache of all classes built from protobuf descriptors + self._classes = {} + + def GetPrototype(self, descriptor): + """Builds a proto2 message class based on the passed in descriptor. + + Passing a descriptor with a fully qualified name matching a previous + invocation will cause the same class to be returned. + + Args: + descriptor: The descriptor to build from. + + Returns: + A class describing the passed in descriptor. + """ + if descriptor.full_name not in self._classes: + descriptor_name = descriptor.name + if sys.version_info[0] < 3: ##PY25 +##!PY25 if str is bytes: # PY2 + descriptor_name = descriptor.name.encode('ascii', 'ignore') + result_class = reflection.GeneratedProtocolMessageType( + descriptor_name, + (message.Message,), + {'DESCRIPTOR': descriptor, '__module__': None}) + # If module not set, it wrongly points to the reflection.py module. + self._classes[descriptor.full_name] = result_class + for field in descriptor.fields: + if field.message_type: + self.GetPrototype(field.message_type) + for extension in result_class.DESCRIPTOR.extensions: + if extension.containing_type.full_name not in self._classes: + self.GetPrototype(extension.containing_type) + extended_class = self._classes[extension.containing_type.full_name] + extended_class.RegisterExtension(extension) + return self._classes[descriptor.full_name] + + def GetMessages(self, files): + """Gets all the messages from a specified file. + + This will find and resolve dependencies, failing if the descriptor + pool cannot satisfy them. + + Args: + files: The file names to extract messages from. + + Returns: + A dictionary mapping proto names to the message classes. This will include + any dependent messages as well as any messages defined in the same file as + a specified message. + """ + result = {} + for file_name in files: + file_desc = self.pool.FindFileByName(file_name) + for name, msg in file_desc.message_types_by_name.iteritems(): + if file_desc.package: + full_name = '.'.join([file_desc.package, name]) + else: + full_name = msg.name + result[full_name] = self.GetPrototype( + self.pool.FindMessageTypeByName(full_name)) + + # While the extension FieldDescriptors are created by the descriptor pool, + # the python classes created in the factory need them to be registered + # explicitly, which is done below. + # + # The call to RegisterExtension will specifically check if the + # extension was already registered on the object and either + # ignore the registration if the original was the same, or raise + # an error if they were different. + + for name, extension in file_desc.extensions_by_name.iteritems(): + if extension.containing_type.full_name not in self._classes: + self.GetPrototype(extension.containing_type) + extended_class = self._classes[extension.containing_type.full_name] + extended_class.RegisterExtension(extension) + return result + + +_FACTORY = MessageFactory() + + +def GetMessages(file_protos): + """Builds a dictionary of all the messages available in a set of files. + + Args: + file_protos: A sequence of file protos to build messages out of. + + Returns: + A dictionary mapping proto names to the message classes. This will include + any dependent messages as well as any messages defined in the same file as + a specified message. + """ + for file_proto in file_protos: + _FACTORY.pool.Add(file_proto) + return _FACTORY.GetMessages([file_proto.name for file_proto in file_protos]) diff --git a/python/google/protobuf/pyext/README b/python/google/protobuf/pyext/README new file mode 100644 index 0000000..6d61cb4 --- /dev/null +++ b/python/google/protobuf/pyext/README @@ -0,0 +1,6 @@ +This is the 'v2' C++ implementation for python proto2. + +It is active when: + +PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp +PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2 diff --git a/python/google/protobuf/pyext/__init__.py b/python/google/protobuf/pyext/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/google/protobuf/pyext/cpp_message.py b/python/google/protobuf/pyext/cpp_message.py new file mode 100644 index 0000000..ba87f8e --- /dev/null +++ b/python/google/protobuf/pyext/cpp_message.py @@ -0,0 +1,61 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Protocol message implementation hooks for C++ implementation. + +Contains helper functions used to create protocol message classes from +Descriptor objects at runtime backed by the protocol buffer C++ API. +""" + +__author__ = 'tibell@google.com (Johan Tibell)' + +from google.protobuf.pyext import _message +from google.protobuf import message + + +def NewMessage(bases, message_descriptor, dictionary): + """Creates a new protocol message *class*.""" + new_bases = [] + for base in bases: + if base is message.Message: + # _message.Message must come before message.Message as it + # overrides methods in that class. + new_bases.append(_message.Message) + new_bases.append(base) + return tuple(new_bases) + + +def InitMessage(message_descriptor, cls): + """Constructs a new message instance (called before instance's __init__).""" + + def SubInit(self, **kwargs): + super(cls, self).__init__(message_descriptor, **kwargs) + cls.__init__ = SubInit + cls.AddDescriptors(message_descriptor) diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc new file mode 100644 index 0000000..cbf42c0 --- /dev/null +++ b/python/google/protobuf/pyext/descriptor.cc @@ -0,0 +1,357 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: petar@google.com (Petar Petrov) + +#include +#include + +#include +#include +#include + +#define C(str) const_cast(str) + +#if PY_MAJOR_VERSION >= 3 + #define PyString_FromStringAndSize PyUnicode_FromStringAndSize + #define PyInt_FromLong PyLong_FromLong + #if PY_VERSION_HEX < 0x03030000 + #error "Python 3.0 - 3.2 are not supported." + #else + #define PyString_AsString(ob) \ + (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AS_STRING(ob)) + #endif +#endif + +namespace google { +namespace protobuf { +namespace python { + + +#ifndef PyVarObject_HEAD_INIT +#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, +#endif +#ifndef Py_TYPE +#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) +#endif + + +static google::protobuf::DescriptorPool* g_descriptor_pool = NULL; + +namespace cfield_descriptor { + +static void Dealloc(CFieldDescriptor* self) { + Py_CLEAR(self->descriptor_field); + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +static PyObject* GetFullName(CFieldDescriptor* self, void *closure) { + return PyString_FromStringAndSize( + self->descriptor->full_name().c_str(), + self->descriptor->full_name().size()); +} + +static PyObject* GetName(CFieldDescriptor *self, void *closure) { + return PyString_FromStringAndSize( + self->descriptor->name().c_str(), + self->descriptor->name().size()); +} + +static PyObject* GetCppType(CFieldDescriptor *self, void *closure) { + return PyInt_FromLong(self->descriptor->cpp_type()); +} + +static PyObject* GetLabel(CFieldDescriptor *self, void *closure) { + return PyInt_FromLong(self->descriptor->label()); +} + +static PyObject* GetID(CFieldDescriptor *self, void *closure) { + return PyLong_FromVoidPtr(self); +} + +static PyGetSetDef Getters[] = { + { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL}, + { C("name"), (getter)GetName, NULL, "last name", NULL}, + { C("cpp_type"), (getter)GetCppType, NULL, "C++ Type", NULL}, + { C("label"), (getter)GetLabel, NULL, "Label", NULL}, + { C("id"), (getter)GetID, NULL, "ID", NULL}, + {NULL} +}; + +} // namespace cfield_descriptor + +PyTypeObject CFieldDescriptor_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + C("google.protobuf.internal." + "_net_proto2___python." + "CFieldDescriptor"), // tp_name + sizeof(CFieldDescriptor), // tp_basicsize + 0, // tp_itemsize + (destructor)cfield_descriptor::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + C("A Field Descriptor"), // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + cfield_descriptor::Getters, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + PyType_GenericAlloc, // tp_alloc + PyType_GenericNew, // tp_new + PyObject_Del, // tp_free +}; + +namespace cdescriptor_pool { + +static void Dealloc(CDescriptorPool* self) { + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +static PyObject* NewCDescriptor( + const google::protobuf::FieldDescriptor* field_descriptor) { + CFieldDescriptor* cfield_descriptor = PyObject_New( + CFieldDescriptor, &CFieldDescriptor_Type); + if (cfield_descriptor == NULL) { + return NULL; + } + cfield_descriptor->descriptor = field_descriptor; + cfield_descriptor->descriptor_field = NULL; + + return reinterpret_cast(cfield_descriptor); +} + +PyObject* FindFieldByName(CDescriptorPool* self, PyObject* name) { + const char* full_field_name = PyString_AsString(name); + if (full_field_name == NULL) { + return NULL; + } + + const google::protobuf::FieldDescriptor* field_descriptor = NULL; + + field_descriptor = self->pool->FindFieldByName(full_field_name); + + if (field_descriptor == NULL) { + PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s", + full_field_name); + return NULL; + } + + return NewCDescriptor(field_descriptor); +} + +PyObject* FindExtensionByName(CDescriptorPool* self, PyObject* arg) { + const char* full_field_name = PyString_AsString(arg); + if (full_field_name == NULL) { + return NULL; + } + + const google::protobuf::FieldDescriptor* field_descriptor = + self->pool->FindExtensionByName(full_field_name); + if (field_descriptor == NULL) { + PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s", + full_field_name); + return NULL; + } + + return NewCDescriptor(field_descriptor); +} + +static PyMethodDef Methods[] = { + { C("FindFieldByName"), + (PyCFunction)FindFieldByName, + METH_O, + C("Searches for a field descriptor by full name.") }, + { C("FindExtensionByName"), + (PyCFunction)FindExtensionByName, + METH_O, + C("Searches for extension descriptor by full name.") }, + {NULL} +}; + +} // namespace cdescriptor_pool + +PyTypeObject CDescriptorPool_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + C("google.protobuf.internal." + "_net_proto2___python." + "CFieldDescriptor"), // tp_name + sizeof(CDescriptorPool), // tp_basicsize + 0, // tp_itemsize + (destructor)cdescriptor_pool::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + C("A Descriptor Pool"), // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + cdescriptor_pool::Methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + PyType_GenericAlloc, // tp_alloc + PyType_GenericNew, // tp_new + PyObject_Del, // tp_free +}; + +google::protobuf::DescriptorPool* GetDescriptorPool() { + if (g_descriptor_pool == NULL) { + g_descriptor_pool = new google::protobuf::DescriptorPool( + google::protobuf::DescriptorPool::generated_pool()); + } + return g_descriptor_pool; +} + +PyObject* Python_NewCDescriptorPool(PyObject* ignored, PyObject* args) { + CDescriptorPool* cdescriptor_pool = PyObject_New( + CDescriptorPool, &CDescriptorPool_Type); + if (cdescriptor_pool == NULL) { + return NULL; + } + cdescriptor_pool->pool = GetDescriptorPool(); + return reinterpret_cast(cdescriptor_pool); +} + + +// Collects errors that occur during proto file building to allow them to be +// propagated in the python exception instead of only living in ERROR logs. +class BuildFileErrorCollector : public google::protobuf::DescriptorPool::ErrorCollector { + public: + BuildFileErrorCollector() : error_message(""), had_errors(false) {} + + void AddError(const string& filename, const string& element_name, + const Message* descriptor, ErrorLocation location, + const string& message) { + // Replicates the logging behavior that happens in the C++ implementation + // when an error collector is not passed in. + if (!had_errors) { + error_message += + ("Invalid proto descriptor for file \"" + filename + "\":\n"); + } + // As this only happens on failure and will result in the program not + // running at all, no effort is made to optimize this string manipulation. + error_message += (" " + element_name + ": " + message + "\n"); + } + + string error_message; + bool had_errors; +}; + +PyObject* Python_BuildFile(PyObject* ignored, PyObject* arg) { + char* message_type; + Py_ssize_t message_len; + + if (PyBytes_AsStringAndSize(arg, &message_type, &message_len) < 0) { + return NULL; + } + + google::protobuf::FileDescriptorProto file_proto; + if (!file_proto.ParseFromArray(message_type, message_len)) { + PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!"); + return NULL; + } + + if (google::protobuf::DescriptorPool::generated_pool()->FindFileByName( + file_proto.name()) != NULL) { + Py_RETURN_NONE; + } + + BuildFileErrorCollector error_collector; + const google::protobuf::FileDescriptor* descriptor = + GetDescriptorPool()->BuildFileCollectingErrors(file_proto, + &error_collector); + if (descriptor == NULL) { + PyErr_Format(PyExc_TypeError, + "Couldn't build proto file into descriptor pool!\n%s", + error_collector.error_message.c_str()); + return NULL; + } + + Py_RETURN_NONE; +} + +bool InitDescriptor() { + CFieldDescriptor_Type.tp_new = PyType_GenericNew; + if (PyType_Ready(&CFieldDescriptor_Type) < 0) + return false; + + CDescriptorPool_Type.tp_new = PyType_GenericNew; + if (PyType_Ready(&CDescriptorPool_Type) < 0) + return false; + + return true; +} + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/pyext/descriptor.h b/python/google/protobuf/pyext/descriptor.h new file mode 100644 index 0000000..d114425 --- /dev/null +++ b/python/google/protobuf/pyext/descriptor.h @@ -0,0 +1,96 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: petar@google.com (Petar Petrov) + +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__ + +#include +#include + +#include + +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#endif + +namespace google { +namespace protobuf { +namespace python { + +typedef struct CFieldDescriptor { + PyObject_HEAD + + // The proto2 descriptor that this object represents. + const google::protobuf::FieldDescriptor* descriptor; + + // Reference to the original field object in the Python DESCRIPTOR. + PyObject* descriptor_field; +} CFieldDescriptor; + +typedef struct { + PyObject_HEAD + + const google::protobuf::DescriptorPool* pool; +} CDescriptorPool; + +extern PyTypeObject CFieldDescriptor_Type; + +extern PyTypeObject CDescriptorPool_Type; + +namespace cdescriptor_pool { + +// Looks up a field by name. Returns a CDescriptor corresponding to +// the field on success, or NULL on failure. +// +// Returns a new reference. +PyObject* FindFieldByName(CDescriptorPool* self, PyObject* name); + +// Looks up an extension by name. Returns a CDescriptor corresponding +// to the field on success, or NULL on failure. +// +// Returns a new reference. +PyObject* FindExtensionByName(CDescriptorPool* self, PyObject* arg); + +} // namespace cdescriptor_pool + +PyObject* Python_NewCDescriptorPool(PyObject* ignored, PyObject* args); +PyObject* Python_BuildFile(PyObject* ignored, PyObject* args); +bool InitDescriptor(); +google::protobuf::DescriptorPool* GetDescriptorPool(); + +} // namespace python +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__ diff --git a/python/google/protobuf/pyext/descriptor_cpp2_test.py b/python/google/protobuf/pyext/descriptor_cpp2_test.py new file mode 100644 index 0000000..3a3ff29 --- /dev/null +++ b/python/google/protobuf/pyext/descriptor_cpp2_test.py @@ -0,0 +1,58 @@ +#! /usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Tests for google.protobuf.pyext behavior.""" + +__author__ = 'anuraag@google.com (Anuraag Agrawal)' + +import os +os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' +os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2' + +# We must set the implementation version above before the google3 imports. +# pylint: disable=g-import-not-at-top +from google.apputils import basetest +from google.protobuf.internal import api_implementation +# Run all tests from the original module by putting them in our namespace. +# pylint: disable=wildcard-import +from google.protobuf.internal.descriptor_test import * + + +class ConfirmCppApi2Test(basetest.TestCase): + + def testImplementationSetting(self): + self.assertEqual('cpp', api_implementation.Type()) + self.assertEqual(2, api_implementation.Version()) + + +if __name__ == '__main__': + basetest.main() diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc new file mode 100644 index 0000000..1e14b42 --- /dev/null +++ b/python/google/protobuf/pyext/extension_dict.cc @@ -0,0 +1,338 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: anuraag@google.com (Anuraag Agrawal) +// Author: tibell@google.com (Johan Tibell) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace python { + +extern google::protobuf::DynamicMessageFactory* global_message_factory; + +namespace extension_dict { + +// TODO(tibell): Always use self->message for clarity, just like in +// RepeatedCompositeContainer. +static google::protobuf::Message* GetMessage(ExtensionDict* self) { + if (self->parent != NULL) { + return self->parent->message; + } else { + return self->message; + } +} + +CFieldDescriptor* InternalGetCDescriptorFromExtension(PyObject* extension) { + PyObject* cdescriptor = PyObject_GetAttrString(extension, "_cdescriptor"); + if (cdescriptor == NULL) { + PyErr_SetString(PyExc_KeyError, "Unregistered extension."); + return NULL; + } + if (!PyObject_TypeCheck(cdescriptor, &CFieldDescriptor_Type)) { + PyErr_SetString(PyExc_TypeError, "Not a CFieldDescriptor"); + Py_DECREF(cdescriptor); + return NULL; + } + CFieldDescriptor* descriptor = + reinterpret_cast(cdescriptor); + return descriptor; +} + +PyObject* len(ExtensionDict* self) { +#if PY_MAJOR_VERSION >= 3 + return PyLong_FromLong(PyDict_Size(self->values)); +#else + return PyInt_FromLong(PyDict_Size(self->values)); +#endif +} + +// TODO(tibell): Use VisitCompositeField. +int ReleaseExtension(ExtensionDict* self, + PyObject* extension, + const google::protobuf::FieldDescriptor* descriptor) { + if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { + if (descriptor->cpp_type() == + google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + if (repeated_composite_container::Release( + reinterpret_cast( + extension)) < 0) { + return -1; + } + } else { + if (repeated_scalar_container::Release( + reinterpret_cast( + extension)) < 0) { + return -1; + } + } + } else if (descriptor->cpp_type() == + google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + if (cmessage::ReleaseSubMessage( + GetMessage(self), descriptor, + reinterpret_cast(extension)) < 0) { + return -1; + } + } + + return 0; +} + +PyObject* subscript(ExtensionDict* self, PyObject* key) { + CFieldDescriptor* cdescriptor = InternalGetCDescriptorFromExtension( + key); + if (cdescriptor == NULL) { + return NULL; + } + ScopedPyObjectPtr py_cdescriptor(reinterpret_cast(cdescriptor)); + const google::protobuf::FieldDescriptor* descriptor = cdescriptor->descriptor; + if (descriptor == NULL) { + return NULL; + } + if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && + descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + return cmessage::InternalGetScalar(self->parent, descriptor); + } + + PyObject* value = PyDict_GetItem(self->values, key); + if (value != NULL) { + Py_INCREF(value); + return value; + } + + if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && + descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + PyObject* sub_message = cmessage::InternalGetSubMessage( + self->parent, cdescriptor); + if (sub_message == NULL) { + return NULL; + } + PyDict_SetItem(self->values, key, sub_message); + return sub_message; + } + + if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { + if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // COPIED + PyObject* py_container = PyObject_CallObject( + reinterpret_cast(&RepeatedCompositeContainer_Type), + NULL); + if (py_container == NULL) { + return NULL; + } + RepeatedCompositeContainer* container = + reinterpret_cast(py_container); + PyObject* field = cdescriptor->descriptor_field; + PyObject* message_type = PyObject_GetAttrString(field, "message_type"); + PyObject* concrete_class = PyObject_GetAttrString(message_type, + "_concrete_class"); + container->owner = self->owner; + container->parent = self->parent; + container->message = self->parent->message; + container->parent_field = cdescriptor; + container->subclass_init = concrete_class; + Py_DECREF(message_type); + PyDict_SetItem(self->values, key, py_container); + return py_container; + } else { + // COPIED + ScopedPyObjectPtr init_args(PyTuple_Pack(2, self->parent, cdescriptor)); + PyObject* py_container = PyObject_CallObject( + reinterpret_cast(&RepeatedScalarContainer_Type), + init_args); + if (py_container == NULL) { + return NULL; + } + PyDict_SetItem(self->values, key, py_container); + return py_container; + } + } + PyErr_SetString(PyExc_ValueError, "control reached unexpected line"); + return NULL; +} + +int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) { + CFieldDescriptor* cdescriptor = InternalGetCDescriptorFromExtension( + key); + if (cdescriptor == NULL) { + return -1; + } + ScopedPyObjectPtr py_cdescriptor(reinterpret_cast(cdescriptor)); + const google::protobuf::FieldDescriptor* descriptor = cdescriptor->descriptor; + if (descriptor->label() != FieldDescriptor::LABEL_OPTIONAL || + descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + PyErr_SetString(PyExc_TypeError, "Extension is repeated and/or composite " + "type"); + return -1; + } + cmessage::AssureWritable(self->parent); + if (cmessage::InternalSetScalar(self->parent, descriptor, value) < 0) { + return -1; + } + // TODO(tibell): We shouldn't write scalars to the cache. + PyDict_SetItem(self->values, key, value); + return 0; +} + +PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) { + CFieldDescriptor* cdescriptor = InternalGetCDescriptorFromExtension( + extension); + if (cdescriptor == NULL) { + return NULL; + } + ScopedPyObjectPtr py_cdescriptor(reinterpret_cast(cdescriptor)); + PyObject* value = PyDict_GetItem(self->values, extension); + if (value != NULL) { + if (ReleaseExtension(self, value, cdescriptor->descriptor) < 0) { + return NULL; + } + } + if (cmessage::ClearFieldByDescriptor(self->parent, + cdescriptor->descriptor) == NULL) { + return NULL; + } + if (PyDict_DelItem(self->values, extension) < 0) { + PyErr_Clear(); + } + Py_RETURN_NONE; +} + +PyObject* HasExtension(ExtensionDict* self, PyObject* extension) { + CFieldDescriptor* cdescriptor = InternalGetCDescriptorFromExtension( + extension); + if (cdescriptor == NULL) { + return NULL; + } + ScopedPyObjectPtr py_cdescriptor(reinterpret_cast(cdescriptor)); + PyObject* result = cmessage::HasFieldByDescriptor( + self->parent, cdescriptor->descriptor); + return result; +} + +PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* name) { + ScopedPyObjectPtr extensions_by_name(PyObject_GetAttrString( + reinterpret_cast(self->parent), "_extensions_by_name")); + if (extensions_by_name == NULL) { + return NULL; + } + PyObject* result = PyDict_GetItem(extensions_by_name, name); + if (result == NULL) { + Py_RETURN_NONE; + } else { + Py_INCREF(result); + return result; + } +} + +int init(ExtensionDict* self, PyObject* args, PyObject* kwargs) { + self->parent = NULL; + self->message = NULL; + self->values = PyDict_New(); + return 0; +} + +void dealloc(ExtensionDict* self) { + Py_CLEAR(self->values); + self->owner.reset(); + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +static PyMappingMethods MpMethods = { + (lenfunc)len, /* mp_length */ + (binaryfunc)subscript, /* mp_subscript */ + (objobjargproc)ass_subscript,/* mp_ass_subscript */ +}; + +#define EDMETHOD(name, args, doc) { #name, (PyCFunction)name, args, doc } +static PyMethodDef Methods[] = { + EDMETHOD(ClearExtension, METH_O, "Clears an extension from the object."), + EDMETHOD(HasExtension, METH_O, "Checks if the object has an extension."), + EDMETHOD(_FindExtensionByName, METH_O, + "Finds an extension by name."), + { NULL, NULL } +}; + +} // namespace extension_dict + +PyTypeObject ExtensionDict_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "google.protobuf.internal." + "cpp._message.ExtensionDict", // tp_name + sizeof(ExtensionDict), // tp_basicsize + 0, // tp_itemsize + (destructor)extension_dict::dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + &extension_dict::MpMethods, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "An extension dict", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + extension_dict::Methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + (initproc)extension_dict::init, // tp_init +}; + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/pyext/extension_dict.h b/python/google/protobuf/pyext/extension_dict.h new file mode 100644 index 0000000..1343001 --- /dev/null +++ b/python/google/protobuf/pyext/extension_dict.h @@ -0,0 +1,123 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: anuraag@google.com (Anuraag Agrawal) +// Author: tibell@google.com (Johan Tibell) + +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_EXTENSION_DICT_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_EXTENSION_DICT_H__ + +#include + +#include +#ifndef _SHARED_PTR_H +#include +#endif + + +namespace google { +namespace protobuf { + +class Message; +class FieldDescriptor; + +using internal::shared_ptr; + +namespace python { + +struct CMessage; +struct CFieldDescriptor; + +typedef struct ExtensionDict { + PyObject_HEAD; + shared_ptr owner; + CMessage* parent; + Message* message; + PyObject* values; +} ExtensionDict; + +extern PyTypeObject ExtensionDict_Type; + +namespace extension_dict { + +// Gets the _cdescriptor reference to a CFieldDescriptor object given a +// python descriptor object. +// +// Returns a new reference. +CFieldDescriptor* InternalGetCDescriptorFromExtension(PyObject* extension); + +// Gets the number of extension values in this ExtensionDict as a python object. +// +// Returns a new reference. +PyObject* len(ExtensionDict* self); + +// Releases extensions referenced outside this dictionary to keep outside +// references alive. +// +// Returns 0 on success, -1 on failure. +int ReleaseExtension(ExtensionDict* self, + PyObject* extension, + const google::protobuf::FieldDescriptor* descriptor); + +// Gets an extension from the dict for the given extension descriptor. +// +// Returns a new reference. +PyObject* subscript(ExtensionDict* self, PyObject* key); + +// Assigns a value to an extension in the dict. Can only be used for singular +// simple types. +// +// Returns 0 on success, -1 on failure. +int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value); + +// Clears an extension from the dict. Will release the extension if there +// is still an external reference left to it. +// +// Returns None on success. +PyObject* ClearExtension(ExtensionDict* self, + PyObject* extension); + +// Checks if the dict has an extension. +// +// Returns a new python boolean reference. +PyObject* HasExtension(ExtensionDict* self, PyObject* extension); + +// Gets an extension from the dict given the extension name as opposed to +// descriptor. +// +// Returns a new reference. +PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* name); + +} // namespace extension_dict +} // namespace python +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_EXTENSION_DICT_H__ diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc new file mode 100644 index 0000000..c45cbf0 --- /dev/null +++ b/python/google/protobuf/pyext/message.cc @@ -0,0 +1,2561 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: anuraag@google.com (Anuraag Agrawal) +// Author: tibell@google.com (Johan Tibell) + +#include + +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include +#include + +#ifndef PyVarObject_HEAD_INIT +#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, +#endif +#ifndef Py_TYPE +#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if PY_MAJOR_VERSION >= 3 + #define PyInt_Check PyLong_Check + #define PyInt_AsLong PyLong_AsLong + #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t + #define PyString_Check PyUnicode_Check + #define PyString_FromString PyUnicode_FromString + #define PyString_FromStringAndSize PyUnicode_FromStringAndSize + #if PY_VERSION_HEX < 0x03030000 + #error "Python 3.0 - 3.2 are not supported." + #else + #define PyString_AsString(ob) \ + (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AS_STRING(ob)) + #endif +#endif + +namespace google { +namespace protobuf { +namespace python { + +// Forward declarations +namespace cmessage { +static PyObject* GetDescriptor(CMessage* self, PyObject* name); +static string GetMessageName(CMessage* self); +int InternalReleaseFieldByDescriptor( + const google::protobuf::FieldDescriptor* field_descriptor, + PyObject* composite_field, + google::protobuf::Message* parent_message); +} // namespace cmessage + +// --------------------------------------------------------------------- +// Visiting the composite children of a CMessage + +struct ChildVisitor { + // Returns 0 on success, -1 on failure. + int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { + return 0; + } + + // Returns 0 on success, -1 on failure. + int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { + return 0; + } + + // Returns 0 on success, -1 on failure. + int VisitCMessage(CMessage* cmessage, + const google::protobuf::FieldDescriptor* field_descriptor) { + return 0; + } +}; + +// Apply a function to a composite field. Does nothing if child is of +// non-composite type. +template +static int VisitCompositeField(const FieldDescriptor* descriptor, + PyObject* child, + Visitor visitor) { + if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { + if (descriptor->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + RepeatedCompositeContainer* container = + reinterpret_cast(child); + if (visitor.VisitRepeatedCompositeContainer(container) == -1) + return -1; + } else { + RepeatedScalarContainer* container = + reinterpret_cast(child); + if (visitor.VisitRepeatedScalarContainer(container) == -1) + return -1; + } + } else if (descriptor->cpp_type() == + google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + CMessage* cmsg = reinterpret_cast(child); + if (visitor.VisitCMessage(cmsg, descriptor) == -1) + return -1; + } + // The ExtensionDict might contain non-composite fields, which we + // skip here. + return 0; +} + +// Visit each composite field and extension field of this CMessage. +// Returns -1 on error and 0 on success. +template +int ForEachCompositeField(CMessage* self, Visitor visitor) { + Py_ssize_t pos = 0; + PyObject* key; + PyObject* field; + + // Visit normal fields. + while (PyDict_Next(self->composite_fields, &pos, &key, &field)) { + PyObject* cdescriptor = cmessage::GetDescriptor(self, key); + if (cdescriptor != NULL) { + const google::protobuf::FieldDescriptor* descriptor = + reinterpret_cast(cdescriptor)->descriptor; + if (VisitCompositeField(descriptor, field, visitor) == -1) + return -1; + } + } + + // Visit extension fields. + if (self->extensions != NULL) { + while (PyDict_Next(self->extensions->values, &pos, &key, &field)) { + CFieldDescriptor* cdescriptor = + extension_dict::InternalGetCDescriptorFromExtension(key); + if (cdescriptor == NULL) + return -1; + if (VisitCompositeField(cdescriptor->descriptor, field, visitor) == -1) + return -1; + } + } + + return 0; +} + +// --------------------------------------------------------------------- + +// Constants used for integer type range checking. +PyObject* kPythonZero; +PyObject* kint32min_py; +PyObject* kint32max_py; +PyObject* kuint32max_py; +PyObject* kint64min_py; +PyObject* kint64max_py; +PyObject* kuint64max_py; + +PyObject* EnumTypeWrapper_class; +PyObject* EncodeError_class; +PyObject* DecodeError_class; +PyObject* PickleError_class; + +// Constant PyString values used for GetAttr/GetItem. +static PyObject* kDESCRIPTOR; +static PyObject* k__descriptors; +static PyObject* kfull_name; +static PyObject* kname; +static PyObject* kmessage_type; +static PyObject* kis_extendable; +static PyObject* kextensions_by_name; +static PyObject* k_extensions_by_name; +static PyObject* k_extensions_by_number; +static PyObject* k_concrete_class; +static PyObject* kfields_by_name; + +static CDescriptorPool* descriptor_pool; + +/* Is 64bit */ +void FormatTypeError(PyObject* arg, char* expected_types) { + PyObject* repr = PyObject_Repr(arg); + if (repr) { + PyErr_Format(PyExc_TypeError, + "%.100s has type %.100s, but expected one of: %s", + PyString_AsString(repr), + Py_TYPE(arg)->tp_name, + expected_types); + Py_DECREF(repr); + } +} + +template +bool CheckAndGetInteger( + PyObject* arg, T* value, PyObject* min, PyObject* max) { + bool is_long = PyLong_Check(arg); +#if PY_MAJOR_VERSION < 3 + if (!PyInt_Check(arg) && !is_long) { + FormatTypeError(arg, "int, long"); + return false; + } + if (PyObject_Compare(min, arg) > 0 || PyObject_Compare(max, arg) < 0) { +#else + if (!is_long) { + FormatTypeError(arg, "int"); + return false; + } + if (PyObject_RichCompareBool(min, arg, Py_LE) != 1 || + PyObject_RichCompareBool(max, arg, Py_GE) != 1) { +#endif + PyObject *s = PyObject_Str(arg); + if (s) { + PyErr_Format(PyExc_ValueError, + "Value out of range: %s", + PyString_AsString(s)); + Py_DECREF(s); + } + return false; + } +#if PY_MAJOR_VERSION < 3 + if (!is_long) { + *value = static_cast(PyInt_AsLong(arg)); + } else // NOLINT +#endif + { + if (min == kPythonZero) { + *value = static_cast(PyLong_AsUnsignedLongLong(arg)); + } else { + *value = static_cast(PyLong_AsLongLong(arg)); + } + } + return true; +} + +// These are referenced by repeated_scalar_container, and must +// be explicitly instantiated. +template bool CheckAndGetInteger( + PyObject*, int32*, PyObject*, PyObject*); +template bool CheckAndGetInteger( + PyObject*, int64*, PyObject*, PyObject*); +template bool CheckAndGetInteger( + PyObject*, uint32*, PyObject*, PyObject*); +template bool CheckAndGetInteger( + PyObject*, uint64*, PyObject*, PyObject*); + +bool CheckAndGetDouble(PyObject* arg, double* value) { + if (!PyInt_Check(arg) && !PyLong_Check(arg) && + !PyFloat_Check(arg)) { + FormatTypeError(arg, "int, long, float"); + return false; + } + *value = PyFloat_AsDouble(arg); + return true; +} + +bool CheckAndGetFloat(PyObject* arg, float* value) { + double double_value; + if (!CheckAndGetDouble(arg, &double_value)) { + return false; + } + *value = static_cast(double_value); + return true; +} + +bool CheckAndGetBool(PyObject* arg, bool* value) { + if (!PyInt_Check(arg) && !PyBool_Check(arg) && !PyLong_Check(arg)) { + FormatTypeError(arg, "int, long, bool"); + return false; + } + *value = static_cast(PyInt_AsLong(arg)); + return true; +} + +bool CheckAndSetString( + PyObject* arg, google::protobuf::Message* message, + const google::protobuf::FieldDescriptor* descriptor, + const google::protobuf::Reflection* reflection, + bool append, + int index) { + GOOGLE_DCHECK(descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING || + descriptor->type() == google::protobuf::FieldDescriptor::TYPE_BYTES); + if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) { + if (!PyBytes_Check(arg) && !PyUnicode_Check(arg)) { + FormatTypeError(arg, "bytes, unicode"); + return false; + } + + if (PyBytes_Check(arg)) { + PyObject* unicode = PyUnicode_FromEncodedObject(arg, "ascii", NULL); + if (unicode == NULL) { + PyObject* repr = PyObject_Repr(arg); + PyErr_Format(PyExc_ValueError, + "%s has type str, but isn't in 7-bit ASCII " + "encoding. Non-ASCII strings must be converted to " + "unicode objects before being added.", + PyString_AsString(repr)); + Py_DECREF(repr); + return false; + } else { + Py_DECREF(unicode); + } + } + } else if (!PyBytes_Check(arg)) { + FormatTypeError(arg, "bytes"); + return false; + } + + PyObject* encoded_string = NULL; + if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) { + if (PyBytes_Check(arg)) { +#if PY_MAJOR_VERSION < 3 + encoded_string = PyString_AsEncodedObject(arg, "utf-8", NULL); +#else + encoded_string = arg; // Already encoded. + Py_INCREF(encoded_string); +#endif + } else { + encoded_string = PyUnicode_AsEncodedObject(arg, "utf-8", NULL); + } + } else { + // In this case field type is "bytes". + encoded_string = arg; + Py_INCREF(encoded_string); + } + + if (encoded_string == NULL) { + return false; + } + + char* value; + Py_ssize_t value_len; + if (PyBytes_AsStringAndSize(encoded_string, &value, &value_len) < 0) { + Py_DECREF(encoded_string); + return false; + } + + string value_string(value, value_len); + if (append) { + reflection->AddString(message, descriptor, value_string); + } else if (index < 0) { + reflection->SetString(message, descriptor, value_string); + } else { + reflection->SetRepeatedString(message, descriptor, index, value_string); + } + Py_DECREF(encoded_string); + return true; +} + +PyObject* ToStringObject( + const google::protobuf::FieldDescriptor* descriptor, string value) { + if (descriptor->type() != google::protobuf::FieldDescriptor::TYPE_STRING) { + return PyBytes_FromStringAndSize(value.c_str(), value.length()); + } + + PyObject* result = PyUnicode_DecodeUTF8(value.c_str(), value.length(), NULL); + // If the string can't be decoded in UTF-8, just return a string object that + // contains the raw bytes. This can't happen if the value was assigned using + // the members of the Python message object, but can happen if the values were + // parsed from the wire (binary). + if (result == NULL) { + PyErr_Clear(); + result = PyBytes_FromStringAndSize(value.c_str(), value.length()); + } + return result; +} + +google::protobuf::DynamicMessageFactory* global_message_factory; + +namespace cmessage { + +static int MaybeReleaseOverlappingOneofField( + CMessage* cmessage, + const google::protobuf::FieldDescriptor* field) { +#ifdef GOOGLE_PROTOBUF_HAS_ONEOF + google::protobuf::Message* message = cmessage->message; + const google::protobuf::Reflection* reflection = message->GetReflection(); + if (!field->containing_oneof() || + !reflection->HasOneof(*message, field->containing_oneof()) || + reflection->HasField(*message, field)) { + // No other field in this oneof, no need to release. + return 0; + } + + const OneofDescriptor* oneof = field->containing_oneof(); + const FieldDescriptor* existing_field = + reflection->GetOneofFieldDescriptor(*message, oneof); + if (existing_field->cpp_type() != google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + // Non-message fields don't need to be released. + return 0; + } + const char* field_name = existing_field->name().c_str(); + PyObject* child_message = PyDict_GetItemString( + cmessage->composite_fields, field_name); + if (child_message == NULL) { + // No python reference to this field so no need to release. + return 0; + } + + if (InternalReleaseFieldByDescriptor( + existing_field, child_message, message) < 0) { + return -1; + } + return PyDict_DelItemString(cmessage->composite_fields, field_name); +#else + return 0; +#endif +} + +// --------------------------------------------------------------------- +// Making a message writable + +static google::protobuf::Message* GetMutableMessage( + CMessage* parent, + const google::protobuf::FieldDescriptor* parent_field) { + google::protobuf::Message* parent_message = parent->message; + const google::protobuf::Reflection* reflection = parent_message->GetReflection(); + if (MaybeReleaseOverlappingOneofField(parent, parent_field) < 0) { + return NULL; + } + return reflection->MutableMessage( + parent_message, parent_field, global_message_factory); +} + +struct FixupMessageReference : public ChildVisitor { + // message must outlive this object. + explicit FixupMessageReference(google::protobuf::Message* message) : + message_(message) {} + + int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { + container->message = message_; + return 0; + } + + int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { + container->message = message_; + return 0; + } + + private: + google::protobuf::Message* message_; +}; + +int AssureWritable(CMessage* self) { + if (self == NULL || !self->read_only) { + return 0; + } + + if (self->parent == NULL) { + // If parent is NULL but we are trying to modify a read-only message, this + // is a reference to a constant default instance that needs to be replaced + // with a mutable top-level message. + const Message* prototype = global_message_factory->GetPrototype( + self->message->GetDescriptor()); + self->message = prototype->New(); + self->owner.reset(self->message); + } else { + // Otherwise, we need a mutable child message. + if (AssureWritable(self->parent) == -1) + return -1; + + // Make self->message writable. + google::protobuf::Message* parent_message = self->parent->message; + google::protobuf::Message* mutable_message = GetMutableMessage( + self->parent, + self->parent_field->descriptor); + if (mutable_message == NULL) { + return -1; + } + self->message = mutable_message; + } + self->read_only = false; + + // When a CMessage is made writable its Message pointer is updated + // to point to a new mutable Message. When that happens we need to + // update any references to the old, read-only CMessage. There are + // three places such references occur: RepeatedScalarContainer, + // RepeatedCompositeContainer, and ExtensionDict. + if (self->extensions != NULL) + self->extensions->message = self->message; + if (ForEachCompositeField(self, FixupMessageReference(self->message)) == -1) + return -1; + + return 0; +} + +// --- Globals: + +static PyObject* GetDescriptor(CMessage* self, PyObject* name) { + PyObject* descriptors = + PyDict_GetItem(Py_TYPE(self)->tp_dict, k__descriptors); + if (descriptors == NULL) { + PyErr_SetString(PyExc_TypeError, "No __descriptors"); + return NULL; + } + + return PyDict_GetItem(descriptors, name); +} + +static const google::protobuf::Message* CreateMessage(const char* message_type) { + string message_name(message_type); + const google::protobuf::Descriptor* descriptor = + GetDescriptorPool()->FindMessageTypeByName(message_name); + if (descriptor == NULL) { + PyErr_SetString(PyExc_TypeError, message_type); + return NULL; + } + return global_message_factory->GetPrototype(descriptor); +} + +// If cmessage_list is not NULL, this function releases values into the +// container CMessages instead of just removing. Repeated composite container +// needs to do this to make sure CMessages stay alive if they're still +// referenced after deletion. Repeated scalar container doesn't need to worry. +int InternalDeleteRepeatedField( + google::protobuf::Message* message, + const google::protobuf::FieldDescriptor* field_descriptor, + PyObject* slice, + PyObject* cmessage_list) { + Py_ssize_t length, from, to, step, slice_length; + const google::protobuf::Reflection* reflection = message->GetReflection(); + int min, max; + length = reflection->FieldSize(*message, field_descriptor); + + if (PyInt_Check(slice) || PyLong_Check(slice)) { + from = to = PyLong_AsLong(slice); + if (from < 0) { + from = to = length + from; + } + step = 1; + min = max = from; + + // Range check. + if (from < 0 || from >= length) { + PyErr_Format(PyExc_IndexError, "list assignment index out of range"); + return -1; + } + } else if (PySlice_Check(slice)) { + from = to = step = slice_length = 0; + PySlice_GetIndicesEx( +#if PY_MAJOR_VERSION < 3 + reinterpret_cast(slice), +#else + slice, +#endif + length, &from, &to, &step, &slice_length); + if (from < to) { + min = from; + max = to - 1; + } else { + min = to + 1; + max = from; + } + } else { + PyErr_SetString(PyExc_TypeError, "list indices must be integers"); + return -1; + } + + Py_ssize_t i = from; + std::vector to_delete(length, false); + while (i >= min && i <= max) { + to_delete[i] = true; + i += step; + } + + to = 0; + for (i = 0; i < length; ++i) { + if (!to_delete[i]) { + if (i != to) { + reflection->SwapElements(message, field_descriptor, i, to); + if (cmessage_list != NULL) { + // If a list of cmessages is passed in (i.e. from a repeated + // composite container), swap those as well to correspond to the + // swaps in the underlying message so they're in the right order + // when we start releasing. + PyObject* tmp = PyList_GET_ITEM(cmessage_list, i); + PyList_SET_ITEM(cmessage_list, i, + PyList_GET_ITEM(cmessage_list, to)); + PyList_SET_ITEM(cmessage_list, to, tmp); + } + } + ++to; + } + } + + while (i > to) { + if (cmessage_list == NULL) { + reflection->RemoveLast(message, field_descriptor); + } else { + CMessage* last_cmessage = reinterpret_cast( + PyList_GET_ITEM(cmessage_list, PyList_GET_SIZE(cmessage_list) - 1)); + repeated_composite_container::ReleaseLastTo( + field_descriptor, message, last_cmessage); + if (PySequence_DelItem(cmessage_list, -1) < 0) { + return -1; + } + } + --i; + } + + return 0; +} + +int InitAttributes(CMessage* self, PyObject* arg, PyObject* kwargs) { + ScopedPyObjectPtr descriptor; + if (arg == NULL) { + descriptor.reset( + PyObject_GetAttr(reinterpret_cast(self), kDESCRIPTOR)); + if (descriptor == NULL) { + return NULL; + } + } else { + descriptor.reset(arg); + descriptor.inc(); + } + ScopedPyObjectPtr is_extendable(PyObject_GetAttr(descriptor, kis_extendable)); + if (is_extendable == NULL) { + return NULL; + } + int retcode = PyObject_IsTrue(is_extendable); + if (retcode == -1) { + return NULL; + } + if (retcode) { + PyObject* py_extension_dict = PyObject_CallObject( + reinterpret_cast(&ExtensionDict_Type), NULL); + if (py_extension_dict == NULL) { + return NULL; + } + ExtensionDict* extension_dict = reinterpret_cast( + py_extension_dict); + extension_dict->parent = self; + extension_dict->message = self->message; + self->extensions = extension_dict; + } + + if (kwargs == NULL) { + return 0; + } + + Py_ssize_t pos = 0; + PyObject* name; + PyObject* value; + while (PyDict_Next(kwargs, &pos, &name, &value)) { + if (!PyString_Check(name)) { + PyErr_SetString(PyExc_ValueError, "Field name must be a string"); + return -1; + } + PyObject* py_cdescriptor = GetDescriptor(self, name); + if (py_cdescriptor == NULL) { + PyErr_Format(PyExc_ValueError, "Protocol message has no \"%s\" field.", + PyString_AsString(name)); + return -1; + } + const google::protobuf::FieldDescriptor* descriptor = + reinterpret_cast(py_cdescriptor)->descriptor; + if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { + ScopedPyObjectPtr container(GetAttr(self, name)); + if (container == NULL) { + return -1; + } + if (descriptor->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + if (repeated_composite_container::Extend( + reinterpret_cast(container.get()), + value) + == NULL) { + return -1; + } + } else { + if (repeated_scalar_container::Extend( + reinterpret_cast(container.get()), + value) == + NULL) { + return -1; + } + } + } else if (descriptor->cpp_type() == + google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + ScopedPyObjectPtr message(GetAttr(self, name)); + if (message == NULL) { + return -1; + } + if (MergeFrom(reinterpret_cast(message.get()), + value) == NULL) { + return -1; + } + } else { + if (SetAttr(self, name, value) < 0) { + return -1; + } + } + } + return 0; +} + +static PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) { + CMessage* self = reinterpret_cast(type->tp_alloc(type, 0)); + if (self == NULL) { + return NULL; + } + + self->message = NULL; + self->parent = NULL; + self->parent_field = NULL; + self->read_only = false; + self->extensions = NULL; + + self->composite_fields = PyDict_New(); + if (self->composite_fields == NULL) { + return NULL; + } + return reinterpret_cast(self); +} + +PyObject* NewEmpty(PyObject* type) { + return New(reinterpret_cast(type), NULL, NULL); +} + +static int Init(CMessage* self, PyObject* args, PyObject* kwargs) { + if (kwargs == NULL) { + // TODO(anuraag): Set error + return -1; + } + + PyObject* descriptor = PyTuple_GetItem(args, 0); + if (descriptor == NULL || PyTuple_Size(args) != 1) { + PyErr_SetString(PyExc_ValueError, "args must contain one arg: descriptor"); + return -1; + } + + ScopedPyObjectPtr py_message_type(PyObject_GetAttr(descriptor, kfull_name)); + if (py_message_type == NULL) { + return -1; + } + + const char* message_type = PyString_AsString(py_message_type.get()); + const google::protobuf::Message* message = CreateMessage(message_type); + if (message == NULL) { + return -1; + } + + self->message = message->New(); + self->owner.reset(self->message); + + if (InitAttributes(self, descriptor, kwargs) < 0) { + return -1; + } + return 0; +} + +// --------------------------------------------------------------------- +// Deallocating a CMessage +// +// Deallocating a CMessage requires that we clear any weak references +// from children to the message being deallocated. + +// Clear the weak reference from the child to the parent. +struct ClearWeakReferences : public ChildVisitor { + int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { + container->parent = NULL; + // The elements in the container have the same parent as the + // container itself, so NULL out that pointer as well. + const Py_ssize_t n = PyList_GET_SIZE(container->child_messages); + for (Py_ssize_t i = 0; i < n; ++i) { + CMessage* child_cmessage = reinterpret_cast( + PyList_GET_ITEM(container->child_messages, i)); + child_cmessage->parent = NULL; + } + return 0; + } + + int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { + container->parent = NULL; + return 0; + } + + int VisitCMessage(CMessage* cmessage, + const google::protobuf::FieldDescriptor* field_descriptor) { + cmessage->parent = NULL; + return 0; + } +}; + +static void Dealloc(CMessage* self) { + // Null out all weak references from children to this message. + GOOGLE_CHECK_EQ(0, ForEachCompositeField(self, ClearWeakReferences())); + + Py_CLEAR(self->extensions); + Py_CLEAR(self->composite_fields); + self->owner.reset(); + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +// --------------------------------------------------------------------- + + +PyObject* IsInitialized(CMessage* self, PyObject* args) { + PyObject* errors = NULL; + if (PyArg_ParseTuple(args, "|O", &errors) < 0) { + return NULL; + } + if (self->message->IsInitialized()) { + Py_RETURN_TRUE; + } + if (errors != NULL) { + ScopedPyObjectPtr initialization_errors( + FindInitializationErrors(self)); + if (initialization_errors == NULL) { + return NULL; + } + ScopedPyObjectPtr extend_name(PyString_FromString("extend")); + if (extend_name == NULL) { + return NULL; + } + ScopedPyObjectPtr result(PyObject_CallMethodObjArgs( + errors, + extend_name.get(), + initialization_errors.get(), + NULL)); + if (result == NULL) { + return NULL; + } + } + Py_RETURN_FALSE; +} + +PyObject* HasFieldByDescriptor( + CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor) { + google::protobuf::Message* message = self->message; + if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) { + PyErr_SetString(PyExc_KeyError, + "Field does not belong to message!"); + return NULL; + } + if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { + PyErr_SetString(PyExc_KeyError, + "Field is repeated. A singular method is required."); + return NULL; + } + bool has_field = + message->GetReflection()->HasField(*message, field_descriptor); + return PyBool_FromLong(has_field ? 1 : 0); +} + +const google::protobuf::FieldDescriptor* FindFieldWithOneofs( + const google::protobuf::Message* message, const char* field_name, bool* in_oneof) { + const google::protobuf::Descriptor* descriptor = message->GetDescriptor(); + const google::protobuf::FieldDescriptor* field_descriptor = + descriptor->FindFieldByName(field_name); + if (field_descriptor == NULL) { + const google::protobuf::OneofDescriptor* oneof_desc = + message->GetDescriptor()->FindOneofByName(field_name); + if (oneof_desc == NULL) { + *in_oneof = false; + return NULL; + } else { + *in_oneof = true; + return message->GetReflection()->GetOneofFieldDescriptor( + *message, oneof_desc); + } + } + return field_descriptor; +} + +PyObject* HasField(CMessage* self, PyObject* arg) { +#if PY_MAJOR_VERSION < 3 + char* field_name; + if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) { +#else + char* field_name = PyUnicode_AsUTF8(arg); + if (!field_name) { +#endif + return NULL; + } + + google::protobuf::Message* message = self->message; + const google::protobuf::Descriptor* descriptor = message->GetDescriptor(); + bool is_in_oneof; + const google::protobuf::FieldDescriptor* field_descriptor = + FindFieldWithOneofs(message, field_name, &is_in_oneof); + if (field_descriptor == NULL) { + if (!is_in_oneof) { + PyErr_Format(PyExc_ValueError, "Unknown field %s.", field_name); + return NULL; + } else { + Py_RETURN_FALSE; + } + } + + if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { + PyErr_Format(PyExc_ValueError, + "Protocol message has no singular \"%s\" field.", field_name); + return NULL; + } + + bool has_field = + message->GetReflection()->HasField(*message, field_descriptor); + if (!has_field && field_descriptor->cpp_type() == + google::protobuf::FieldDescriptor::CPPTYPE_ENUM) { + // We may have an invalid enum value stored in the UnknownFieldSet and need + // to check presence in there as well. + const google::protobuf::UnknownFieldSet& unknown_field_set = + message->GetReflection()->GetUnknownFields(*message); + for (int i = 0; i < unknown_field_set.field_count(); ++i) { + if (unknown_field_set.field(i).number() == field_descriptor->number()) { + Py_RETURN_TRUE; + } + } + Py_RETURN_FALSE; + } + return PyBool_FromLong(has_field ? 1 : 0); +} + +PyObject* ClearExtension(CMessage* self, PyObject* arg) { + if (self->extensions != NULL) { + return extension_dict::ClearExtension(self->extensions, arg); + } + PyErr_SetString(PyExc_TypeError, "Message is not extendable"); + return NULL; +} + +PyObject* HasExtension(CMessage* self, PyObject* arg) { + if (self->extensions != NULL) { + return extension_dict::HasExtension(self->extensions, arg); + } + PyErr_SetString(PyExc_TypeError, "Message is not extendable"); + return NULL; +} + +// --------------------------------------------------------------------- +// Releasing messages +// +// The Python API's ClearField() and Clear() methods behave +// differently than their C++ counterparts. While the C++ versions +// clears the children the Python versions detaches the children, +// without touching their content. This impedance mismatch causes +// some complexity in the implementation, which is captured in this +// section. +// +// When a CMessage field is cleared we need to: +// +// * Release the Message used as the backing store for the CMessage +// from its parent. +// +// * Change the owner field of the released CMessage and all of its +// children to point to the newly released Message. +// +// * Clear the weak references from the released CMessage to the +// parent. +// +// When a RepeatedCompositeContainer field is cleared we need to: +// +// * Release all the Message used as the backing store for the +// CMessages stored in the container. +// +// * Change the owner field of all the released CMessage and all of +// their children to point to the newly released Messages. +// +// * Clear the weak references from the released container to the +// parent. + +struct SetOwnerVisitor : public ChildVisitor { + // new_owner must outlive this object. + explicit SetOwnerVisitor(const shared_ptr& new_owner) + : new_owner_(new_owner) {} + + int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { + repeated_composite_container::SetOwner(container, new_owner_); + return 0; + } + + int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { + repeated_scalar_container::SetOwner(container, new_owner_); + return 0; + } + + int VisitCMessage(CMessage* cmessage, + const google::protobuf::FieldDescriptor* field_descriptor) { + return SetOwner(cmessage, new_owner_); + } + + private: + const shared_ptr& new_owner_; +}; + +// Change the owner of this CMessage and all its children, recursively. +int SetOwner(CMessage* self, const shared_ptr& new_owner) { + self->owner = new_owner; + if (ForEachCompositeField(self, SetOwnerVisitor(new_owner)) == -1) + return -1; + return 0; +} + +// Releases the message specified by 'field' and returns the +// pointer. If the field does not exist a new message is created using +// 'descriptor'. The caller takes ownership of the returned pointer. +Message* ReleaseMessage(google::protobuf::Message* message, + const google::protobuf::Descriptor* descriptor, + const google::protobuf::FieldDescriptor* field_descriptor) { + Message* released_message = message->GetReflection()->ReleaseMessage( + message, field_descriptor, global_message_factory); + // ReleaseMessage will return NULL which differs from + // child_cmessage->message, if the field does not exist. In this case, + // the latter points to the default instance via a const_cast<>, so we + // have to reset it to a new mutable object since we are taking ownership. + if (released_message == NULL) { + const Message* prototype = global_message_factory->GetPrototype( + descriptor); + GOOGLE_DCHECK(prototype != NULL); + released_message = prototype->New(); + } + + return released_message; +} + +int ReleaseSubMessage(google::protobuf::Message* message, + const google::protobuf::FieldDescriptor* field_descriptor, + CMessage* child_cmessage) { + // Release the Message + shared_ptr released_message(ReleaseMessage( + message, child_cmessage->message->GetDescriptor(), field_descriptor)); + child_cmessage->message = released_message.get(); + child_cmessage->owner.swap(released_message); + child_cmessage->parent = NULL; + child_cmessage->parent_field = NULL; + child_cmessage->read_only = false; + return ForEachCompositeField(child_cmessage, + SetOwnerVisitor(child_cmessage->owner)); +} + +struct ReleaseChild : public ChildVisitor { + // message must outlive this object. + explicit ReleaseChild(google::protobuf::Message* parent_message) : + parent_message_(parent_message) {} + + int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { + return repeated_composite_container::Release( + reinterpret_cast(container)); + } + + int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { + return repeated_scalar_container::Release( + reinterpret_cast(container)); + } + + int VisitCMessage(CMessage* cmessage, + const google::protobuf::FieldDescriptor* field_descriptor) { + return ReleaseSubMessage(parent_message_, field_descriptor, + reinterpret_cast(cmessage)); + } + + google::protobuf::Message* parent_message_; +}; + +int InternalReleaseFieldByDescriptor( + const google::protobuf::FieldDescriptor* field_descriptor, + PyObject* composite_field, + google::protobuf::Message* parent_message) { + return VisitCompositeField( + field_descriptor, + composite_field, + ReleaseChild(parent_message)); +} + +int InternalReleaseField(CMessage* self, PyObject* composite_field, + PyObject* name) { + PyObject* cdescriptor = GetDescriptor(self, name); + if (cdescriptor != NULL) { + const google::protobuf::FieldDescriptor* descriptor = + reinterpret_cast(cdescriptor)->descriptor; + return InternalReleaseFieldByDescriptor( + descriptor, composite_field, self->message); + } + + return 0; +} + +PyObject* ClearFieldByDescriptor( + CMessage* self, + const google::protobuf::FieldDescriptor* descriptor) { + if (!FIELD_BELONGS_TO_MESSAGE(descriptor, self->message)) { + PyErr_SetString(PyExc_KeyError, + "Field does not belong to message!"); + return NULL; + } + AssureWritable(self); + self->message->GetReflection()->ClearField(self->message, descriptor); + Py_RETURN_NONE; +} + +PyObject* ClearField(CMessage* self, PyObject* arg) { + char* field_name; + if (!PyString_Check(arg)) { + PyErr_SetString(PyExc_TypeError, "field name must be a string"); + return NULL; + } +#if PY_MAJOR_VERSION < 3 + if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) { + return NULL; + } +#else + field_name = PyUnicode_AsUTF8(arg); +#endif + AssureWritable(self); + google::protobuf::Message* message = self->message; + const google::protobuf::Descriptor* descriptor = message->GetDescriptor(); + ScopedPyObjectPtr arg_in_oneof; + bool is_in_oneof; + const google::protobuf::FieldDescriptor* field_descriptor = + FindFieldWithOneofs(message, field_name, &is_in_oneof); + if (field_descriptor == NULL) { + if (!is_in_oneof) { + PyErr_Format(PyExc_ValueError, + "Protocol message has no \"%s\" field.", field_name); + return NULL; + } else { + Py_RETURN_NONE; + } + } else if (is_in_oneof) { + arg_in_oneof.reset(PyString_FromString(field_descriptor->name().c_str())); + arg = arg_in_oneof.get(); + } + + PyObject* composite_field = PyDict_GetItem(self->composite_fields, + arg); + + // Only release the field if there's a possibility that there are + // references to it. + if (composite_field != NULL) { + if (InternalReleaseField(self, composite_field, arg) < 0) { + return NULL; + } + PyDict_DelItem(self->composite_fields, arg); + } + message->GetReflection()->ClearField(message, field_descriptor); + if (field_descriptor->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_ENUM) { + google::protobuf::UnknownFieldSet* unknown_field_set = + message->GetReflection()->MutableUnknownFields(message); + unknown_field_set->DeleteByNumber(field_descriptor->number()); + } + + Py_RETURN_NONE; +} + +PyObject* Clear(CMessage* self) { + AssureWritable(self); + if (ForEachCompositeField(self, ReleaseChild(self->message)) == -1) + return NULL; + + // The old ExtensionDict still aliases this CMessage, but all its + // fields have been released. + if (self->extensions != NULL) { + Py_CLEAR(self->extensions); + PyObject* py_extension_dict = PyObject_CallObject( + reinterpret_cast(&ExtensionDict_Type), NULL); + if (py_extension_dict == NULL) { + return NULL; + } + ExtensionDict* extension_dict = reinterpret_cast( + py_extension_dict); + extension_dict->parent = self; + extension_dict->message = self->message; + self->extensions = extension_dict; + } + PyDict_Clear(self->composite_fields); + self->message->Clear(); + Py_RETURN_NONE; +} + +// --------------------------------------------------------------------- + +static string GetMessageName(CMessage* self) { + if (self->parent_field != NULL) { + return self->parent_field->descriptor->full_name(); + } else { + return self->message->GetDescriptor()->full_name(); + } +} + +static PyObject* SerializeToString(CMessage* self, PyObject* args) { + if (!self->message->IsInitialized()) { + ScopedPyObjectPtr errors(FindInitializationErrors(self)); + if (errors == NULL) { + return NULL; + } + ScopedPyObjectPtr comma(PyString_FromString(",")); + if (comma == NULL) { + return NULL; + } + ScopedPyObjectPtr joined( + PyObject_CallMethod(comma.get(), "join", "O", errors.get())); + if (joined == NULL) { + return NULL; + } + PyErr_Format(EncodeError_class, "Message %s is missing required fields: %s", + GetMessageName(self).c_str(), PyString_AsString(joined.get())); + return NULL; + } + int size = self->message->ByteSize(); + if (size <= 0) { + return PyBytes_FromString(""); + } + PyObject* result = PyBytes_FromStringAndSize(NULL, size); + if (result == NULL) { + return NULL; + } + char* buffer = PyBytes_AS_STRING(result); + self->message->SerializeWithCachedSizesToArray( + reinterpret_cast(buffer)); + return result; +} + +static PyObject* SerializePartialToString(CMessage* self) { + string contents; + self->message->SerializePartialToString(&contents); + return PyBytes_FromStringAndSize(contents.c_str(), contents.size()); +} + +// Formats proto fields for ascii dumps using python formatting functions where +// appropriate. +class PythonFieldValuePrinter : public google::protobuf::TextFormat::FieldValuePrinter { + public: + PythonFieldValuePrinter() : float_holder_(PyFloat_FromDouble(0)) {} + + // Python has some differences from C++ when printing floating point numbers. + // + // 1) Trailing .0 is always printed. + // 2) Outputted is rounded to 12 digits. + // + // We override floating point printing with the C-API function for printing + // Python floats to ensure consistency. + string PrintFloat(float value) const { return PrintDouble(value); } + string PrintDouble(double value) const { + reinterpret_cast(float_holder_.get())->ob_fval = value; + ScopedPyObjectPtr s(PyObject_Str(float_holder_.get())); + if (s == NULL) return string(); +#if PY_MAJOR_VERSION < 3 + char *cstr = PyBytes_AS_STRING(static_cast(s)); +#else + char *cstr = PyUnicode_AsUTF8(s); +#endif + return string(cstr); + } + + private: + // Holder for a python float object which we use to allow us to use + // the Python API for printing doubles. We initialize once and then + // directly modify it for every float printed to save on allocations + // and refcounting. + ScopedPyObjectPtr float_holder_; +}; + +static PyObject* ToStr(CMessage* self) { + google::protobuf::TextFormat::Printer printer; + // Passes ownership + printer.SetDefaultFieldValuePrinter(new PythonFieldValuePrinter()); + printer.SetHideUnknownFields(true); + string output; + if (!printer.PrintToString(*self->message, &output)) { + PyErr_SetString(PyExc_ValueError, "Unable to convert message to str"); + return NULL; + } + return PyString_FromString(output.c_str()); +} + +PyObject* MergeFrom(CMessage* self, PyObject* arg) { + CMessage* other_message; + if (!PyObject_TypeCheck(reinterpret_cast(arg), &CMessage_Type)) { + PyErr_SetString(PyExc_TypeError, "Must be a message"); + return NULL; + } + + other_message = reinterpret_cast(arg); + if (other_message->message->GetDescriptor() != + self->message->GetDescriptor()) { + PyErr_Format(PyExc_TypeError, + "Tried to merge from a message with a different type. " + "to: %s, from: %s", + self->message->GetDescriptor()->full_name().c_str(), + other_message->message->GetDescriptor()->full_name().c_str()); + return NULL; + } + AssureWritable(self); + + // TODO(tibell): Message::MergeFrom might turn some child Messages + // into mutable messages, invalidating the message field in the + // corresponding CMessages. We should run a FixupMessageReferences + // pass here. + + self->message->MergeFrom(*other_message->message); + Py_RETURN_NONE; +} + +static PyObject* CopyFrom(CMessage* self, PyObject* arg) { + CMessage* other_message; + if (!PyObject_TypeCheck(reinterpret_cast(arg), &CMessage_Type)) { + PyErr_SetString(PyExc_TypeError, "Must be a message"); + return NULL; + } + + other_message = reinterpret_cast(arg); + + if (self == other_message) { + Py_RETURN_NONE; + } + + if (other_message->message->GetDescriptor() != + self->message->GetDescriptor()) { + PyErr_Format(PyExc_TypeError, + "Tried to copy from a message with a different type. " + "to: %s, from: %s", + self->message->GetDescriptor()->full_name().c_str(), + other_message->message->GetDescriptor()->full_name().c_str()); + return NULL; + } + + AssureWritable(self); + + // CopyFrom on the message will not clean up self->composite_fields, + // which can leave us in an inconsistent state, so clear it out here. + Clear(self); + + self->message->CopyFrom(*other_message->message); + + Py_RETURN_NONE; +} + +static PyObject* MergeFromString(CMessage* self, PyObject* arg) { + const void* data; + Py_ssize_t data_length; + if (PyObject_AsReadBuffer(arg, &data, &data_length) < 0) { + return NULL; + } + + AssureWritable(self); + google::protobuf::io::CodedInputStream input( + reinterpret_cast(data), data_length); + input.SetExtensionRegistry(GetDescriptorPool(), global_message_factory); + bool success = self->message->MergePartialFromCodedStream(&input); + if (success) { + return PyInt_FromLong(input.CurrentPosition()); + } else { + PyErr_Format(DecodeError_class, "Error parsing message"); + return NULL; + } +} + +static PyObject* ParseFromString(CMessage* self, PyObject* arg) { + if (Clear(self) == NULL) { + return NULL; + } + return MergeFromString(self, arg); +} + +static PyObject* ByteSize(CMessage* self, PyObject* args) { + return PyLong_FromLong(self->message->ByteSize()); +} + +static PyObject* RegisterExtension(PyObject* cls, + PyObject* extension_handle) { + ScopedPyObjectPtr message_descriptor(PyObject_GetAttr(cls, kDESCRIPTOR)); + if (message_descriptor == NULL) { + return NULL; + } + if (PyObject_SetAttrString(extension_handle, "containing_type", + message_descriptor) < 0) { + return NULL; + } + ScopedPyObjectPtr extensions_by_name( + PyObject_GetAttr(cls, k_extensions_by_name)); + if (extensions_by_name == NULL) { + PyErr_SetString(PyExc_TypeError, "no extensions_by_name on class"); + return NULL; + } + ScopedPyObjectPtr full_name(PyObject_GetAttr(extension_handle, kfull_name)); + if (full_name == NULL) { + return NULL; + } + if (PyDict_SetItem(extensions_by_name, full_name, extension_handle) < 0) { + return NULL; + } + + // Also store a mapping from extension number to implementing class. + ScopedPyObjectPtr extensions_by_number( + PyObject_GetAttr(cls, k_extensions_by_number)); + if (extensions_by_number == NULL) { + PyErr_SetString(PyExc_TypeError, "no extensions_by_number on class"); + return NULL; + } + ScopedPyObjectPtr number(PyObject_GetAttrString(extension_handle, "number")); + if (number == NULL) { + return NULL; + } + if (PyDict_SetItem(extensions_by_number, number, extension_handle) < 0) { + return NULL; + } + + CFieldDescriptor* cdescriptor = + extension_dict::InternalGetCDescriptorFromExtension(extension_handle); + ScopedPyObjectPtr py_cdescriptor(reinterpret_cast(cdescriptor)); + if (cdescriptor == NULL) { + return NULL; + } + Py_INCREF(extension_handle); + cdescriptor->descriptor_field = extension_handle; + const google::protobuf::FieldDescriptor* descriptor = cdescriptor->descriptor; + // Check if it's a message set + if (descriptor->is_extension() && + descriptor->containing_type()->options().message_set_wire_format() && + descriptor->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE && + descriptor->message_type() == descriptor->extension_scope() && + descriptor->label() == google::protobuf::FieldDescriptor::LABEL_OPTIONAL) { + ScopedPyObjectPtr message_name(PyString_FromStringAndSize( + descriptor->message_type()->full_name().c_str(), + descriptor->message_type()->full_name().size())); + if (message_name == NULL) { + return NULL; + } + PyDict_SetItem(extensions_by_name, message_name, extension_handle); + } + + Py_RETURN_NONE; +} + +static PyObject* SetInParent(CMessage* self, PyObject* args) { + AssureWritable(self); + Py_RETURN_NONE; +} + +static PyObject* WhichOneof(CMessage* self, PyObject* arg) { + char* oneof_name; + if (!PyString_Check(arg)) { + PyErr_SetString(PyExc_TypeError, "field name must be a string"); + return NULL; + } + oneof_name = PyString_AsString(arg); + if (oneof_name == NULL) { + return NULL; + } + const google::protobuf::OneofDescriptor* oneof_desc = + self->message->GetDescriptor()->FindOneofByName(oneof_name); + if (oneof_desc == NULL) { + PyErr_Format(PyExc_ValueError, + "Protocol message has no oneof \"%s\" field.", oneof_name); + return NULL; + } + const google::protobuf::FieldDescriptor* field_in_oneof = + self->message->GetReflection()->GetOneofFieldDescriptor( + *self->message, oneof_desc); + if (field_in_oneof == NULL) { + Py_RETURN_NONE; + } else { + return PyString_FromString(field_in_oneof->name().c_str()); + } +} + +static PyObject* ListFields(CMessage* self) { + vector fields; + self->message->GetReflection()->ListFields(*self->message, &fields); + + PyObject* descriptor = PyDict_GetItem(Py_TYPE(self)->tp_dict, kDESCRIPTOR); + if (descriptor == NULL) { + return NULL; + } + ScopedPyObjectPtr fields_by_name( + PyObject_GetAttr(descriptor, kfields_by_name)); + if (fields_by_name == NULL) { + return NULL; + } + ScopedPyObjectPtr extensions_by_name(PyObject_GetAttr( + reinterpret_cast(Py_TYPE(self)), k_extensions_by_name)); + if (extensions_by_name == NULL) { + PyErr_SetString(PyExc_ValueError, "no extensionsbyname"); + return NULL; + } + // Normally, the list will be exactly the size of the fields. + PyObject* all_fields = PyList_New(fields.size()); + if (all_fields == NULL) { + return NULL; + } + + // When there are unknown extensions, the py list will *not* contain + // the field information. Thus the actual size of the py list will be + // smaller than the size of fields. Set the actual size at the end. + Py_ssize_t actual_size = 0; + for (Py_ssize_t i = 0; i < fields.size(); ++i) { + ScopedPyObjectPtr t(PyTuple_New(2)); + if (t == NULL) { + Py_DECREF(all_fields); + return NULL; + } + + if (fields[i]->is_extension()) { + const string& field_name = fields[i]->full_name(); + PyObject* extension_field = PyDict_GetItemString(extensions_by_name, + field_name.c_str()); + if (extension_field == NULL) { + // If we couldn't fetch extension_field, it means the module that + // defines this extension has not been explicitly imported in Python + // code, and the extension hasn't been registered. There's nothing much + // we can do about this, so just skip it in the output to match the + // behavior of the python implementation. + continue; + } + PyObject* extensions = reinterpret_cast(self->extensions); + if (extensions == NULL) { + Py_DECREF(all_fields); + return NULL; + } + // 'extension' reference later stolen by PyTuple_SET_ITEM. + PyObject* extension = PyObject_GetItem(extensions, extension_field); + if (extension == NULL) { + Py_DECREF(all_fields); + return NULL; + } + Py_INCREF(extension_field); + PyTuple_SET_ITEM(t.get(), 0, extension_field); + // Steals reference to 'extension' + PyTuple_SET_ITEM(t.get(), 1, extension); + } else { + const string& field_name = fields[i]->name(); + ScopedPyObjectPtr py_field_name(PyString_FromStringAndSize( + field_name.c_str(), field_name.length())); + if (py_field_name == NULL) { + PyErr_SetString(PyExc_ValueError, "bad string"); + Py_DECREF(all_fields); + return NULL; + } + PyObject* field_descriptor = + PyDict_GetItem(fields_by_name, py_field_name); + if (field_descriptor == NULL) { + Py_DECREF(all_fields); + return NULL; + } + + PyObject* field_value = GetAttr(self, py_field_name); + if (field_value == NULL) { + PyErr_SetObject(PyExc_ValueError, py_field_name); + Py_DECREF(all_fields); + return NULL; + } + Py_INCREF(field_descriptor); + PyTuple_SET_ITEM(t.get(), 0, field_descriptor); + PyTuple_SET_ITEM(t.get(), 1, field_value); + } + PyList_SET_ITEM(all_fields, actual_size, t.release()); + ++actual_size; + } + Py_SIZE(all_fields) = actual_size; + return all_fields; +} + +PyObject* FindInitializationErrors(CMessage* self) { + google::protobuf::Message* message = self->message; + vector errors; + message->FindInitializationErrors(&errors); + + PyObject* error_list = PyList_New(errors.size()); + if (error_list == NULL) { + return NULL; + } + for (Py_ssize_t i = 0; i < errors.size(); ++i) { + const string& error = errors[i]; + PyObject* error_string = PyString_FromStringAndSize( + error.c_str(), error.length()); + if (error_string == NULL) { + Py_DECREF(error_list); + return NULL; + } + PyList_SET_ITEM(error_list, i, error_string); + } + return error_list; +} + +static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) { + if (!PyObject_TypeCheck(other, &CMessage_Type)) { + if (opid == Py_EQ) { + Py_RETURN_FALSE; + } else if (opid == Py_NE) { + Py_RETURN_TRUE; + } + } + if (opid == Py_EQ || opid == Py_NE) { + ScopedPyObjectPtr self_fields(ListFields(self)); + ScopedPyObjectPtr other_fields(ListFields( + reinterpret_cast(other))); + return PyObject_RichCompare(self_fields, other_fields, opid); + } else { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } +} + +PyObject* InternalGetScalar( + CMessage* self, + const google::protobuf::FieldDescriptor* field_descriptor) { + google::protobuf::Message* message = self->message; + const google::protobuf::Reflection* reflection = message->GetReflection(); + + if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) { + PyErr_SetString( + PyExc_KeyError, "Field does not belong to message!"); + return NULL; + } + + PyObject* result = NULL; + switch (field_descriptor->cpp_type()) { + case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { + int32 value = reflection->GetInt32(*message, field_descriptor); + result = PyInt_FromLong(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { + int64 value = reflection->GetInt64(*message, field_descriptor); + result = PyLong_FromLongLong(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { + uint32 value = reflection->GetUInt32(*message, field_descriptor); + result = PyInt_FromSize_t(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { + uint64 value = reflection->GetUInt64(*message, field_descriptor); + result = PyLong_FromUnsignedLongLong(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { + float value = reflection->GetFloat(*message, field_descriptor); + result = PyFloat_FromDouble(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { + double value = reflection->GetDouble(*message, field_descriptor); + result = PyFloat_FromDouble(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { + bool value = reflection->GetBool(*message, field_descriptor); + result = PyBool_FromLong(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { + string value = reflection->GetString(*message, field_descriptor); + result = ToStringObject(field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { + if (!message->GetReflection()->HasField(*message, field_descriptor)) { + // Look for the value in the unknown fields. + google::protobuf::UnknownFieldSet* unknown_field_set = + message->GetReflection()->MutableUnknownFields(message); + for (int i = 0; i < unknown_field_set->field_count(); ++i) { + if (unknown_field_set->field(i).number() == + field_descriptor->number()) { + result = PyInt_FromLong(unknown_field_set->field(i).varint()); + break; + } + } + } + + if (result == NULL) { + const google::protobuf::EnumValueDescriptor* enum_value = + message->GetReflection()->GetEnum(*message, field_descriptor); + result = PyInt_FromLong(enum_value->number()); + } + break; + } + default: + PyErr_Format( + PyExc_SystemError, "Getting a value from a field of unknown type %d", + field_descriptor->cpp_type()); + } + + return result; +} + +PyObject* InternalGetSubMessage(CMessage* self, + CFieldDescriptor* cfield_descriptor) { + PyObject* field = cfield_descriptor->descriptor_field; + ScopedPyObjectPtr message_type(PyObject_GetAttr(field, kmessage_type)); + if (message_type == NULL) { + return NULL; + } + ScopedPyObjectPtr concrete_class( + PyObject_GetAttr(message_type, k_concrete_class)); + if (concrete_class == NULL) { + return NULL; + } + PyObject* py_cmsg = cmessage::NewEmpty(concrete_class); + if (py_cmsg == NULL) { + return NULL; + } + if (!PyObject_TypeCheck(py_cmsg, &CMessage_Type)) { + PyErr_SetString(PyExc_TypeError, "Not a CMessage!"); + } + CMessage* cmsg = reinterpret_cast(py_cmsg); + + const google::protobuf::FieldDescriptor* field_descriptor = + cfield_descriptor->descriptor; + const google::protobuf::Reflection* reflection = self->message->GetReflection(); + const google::protobuf::Message& sub_message = reflection->GetMessage( + *self->message, field_descriptor, global_message_factory); + cmsg->owner = self->owner; + cmsg->parent = self; + cmsg->parent_field = cfield_descriptor; + cmsg->read_only = !reflection->HasField(*self->message, field_descriptor); + cmsg->message = const_cast(&sub_message); + + if (InitAttributes(cmsg, NULL, NULL) < 0) { + Py_DECREF(py_cmsg); + return NULL; + } + return py_cmsg; +} + +int InternalSetScalar( + CMessage* self, + const google::protobuf::FieldDescriptor* field_descriptor, + PyObject* arg) { + google::protobuf::Message* message = self->message; + const google::protobuf::Reflection* reflection = message->GetReflection(); + + if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) { + PyErr_SetString( + PyExc_KeyError, "Field does not belong to message!"); + return -1; + } + + if (MaybeReleaseOverlappingOneofField(self, field_descriptor) < 0) { + return -1; + } + + switch (field_descriptor->cpp_type()) { + case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { + GOOGLE_CHECK_GET_INT32(arg, value, -1); + reflection->SetInt32(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { + GOOGLE_CHECK_GET_INT64(arg, value, -1); + reflection->SetInt64(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { + GOOGLE_CHECK_GET_UINT32(arg, value, -1); + reflection->SetUInt32(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { + GOOGLE_CHECK_GET_UINT64(arg, value, -1); + reflection->SetUInt64(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { + GOOGLE_CHECK_GET_FLOAT(arg, value, -1); + reflection->SetFloat(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { + GOOGLE_CHECK_GET_DOUBLE(arg, value, -1); + reflection->SetDouble(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { + GOOGLE_CHECK_GET_BOOL(arg, value, -1); + reflection->SetBool(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { + if (!CheckAndSetString( + arg, message, field_descriptor, reflection, false, -1)) { + return -1; + } + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { + GOOGLE_CHECK_GET_INT32(arg, value, -1); + const google::protobuf::EnumDescriptor* enum_descriptor = + field_descriptor->enum_type(); + const google::protobuf::EnumValueDescriptor* enum_value = + enum_descriptor->FindValueByNumber(value); + if (enum_value != NULL) { + reflection->SetEnum(message, field_descriptor, enum_value); + } else { + PyErr_Format(PyExc_ValueError, "Unknown enum value: %d", value); + return -1; + } + break; + } + default: + PyErr_Format( + PyExc_SystemError, "Setting value to a field of unknown type %d", + field_descriptor->cpp_type()); + return -1; + } + + return 0; +} + +PyObject* FromString(PyTypeObject* cls, PyObject* serialized) { + PyObject* py_cmsg = PyObject_CallObject( + reinterpret_cast(cls), NULL); + if (py_cmsg == NULL) { + return NULL; + } + CMessage* cmsg = reinterpret_cast(py_cmsg); + + ScopedPyObjectPtr py_length(MergeFromString(cmsg, serialized)); + if (py_length == NULL) { + Py_DECREF(py_cmsg); + return NULL; + } + + if (InitAttributes(cmsg, NULL, NULL) < 0) { + Py_DECREF(py_cmsg); + return NULL; + } + return py_cmsg; +} + +static PyObject* AddDescriptors(PyTypeObject* cls, + PyObject* descriptor) { + if (PyObject_SetAttr(reinterpret_cast(cls), + k_extensions_by_name, PyDict_New()) < 0) { + return NULL; + } + if (PyObject_SetAttr(reinterpret_cast(cls), + k_extensions_by_number, PyDict_New()) < 0) { + return NULL; + } + + ScopedPyObjectPtr field_descriptors(PyDict_New()); + + ScopedPyObjectPtr fields(PyObject_GetAttrString(descriptor, "fields")); + if (fields == NULL) { + return NULL; + } + + ScopedPyObjectPtr _NUMBER_string(PyString_FromString("_FIELD_NUMBER")); + if (_NUMBER_string == NULL) { + return NULL; + } + + const Py_ssize_t fields_size = PyList_GET_SIZE(fields.get()); + for (int i = 0; i < fields_size; ++i) { + PyObject* field = PyList_GET_ITEM(fields.get(), i); + ScopedPyObjectPtr field_name(PyObject_GetAttr(field, kname)); + ScopedPyObjectPtr full_field_name(PyObject_GetAttr(field, kfull_name)); + if (field_name == NULL || full_field_name == NULL) { + PyErr_SetString(PyExc_TypeError, "Name is null"); + return NULL; + } + + PyObject* field_descriptor = + cdescriptor_pool::FindFieldByName(descriptor_pool, full_field_name); + if (field_descriptor == NULL) { + PyErr_SetString(PyExc_TypeError, "Couldn't find field"); + return NULL; + } + Py_INCREF(field); + CFieldDescriptor* cfield_descriptor = reinterpret_cast( + field_descriptor); + cfield_descriptor->descriptor_field = field; + if (PyDict_SetItem(field_descriptors, field_name, field_descriptor) < 0) { + return NULL; + } + + // The FieldDescriptor's name field might either be of type bytes or + // of type unicode, depending on whether the FieldDescriptor was + // parsed from a serialized message or read from the + // _pb2.py module. + ScopedPyObjectPtr field_name_upcased( + PyObject_CallMethod(field_name, "upper", NULL)); + if (field_name_upcased == NULL) { + return NULL; + } + + ScopedPyObjectPtr field_number_name(PyObject_CallMethod( + field_name_upcased, "__add__", "(O)", _NUMBER_string.get())); + if (field_number_name == NULL) { + return NULL; + } + + ScopedPyObjectPtr number(PyInt_FromLong( + cfield_descriptor->descriptor->number())); + if (number == NULL) { + return NULL; + } + if (PyObject_SetAttr(reinterpret_cast(cls), + field_number_name, number) == -1) { + return NULL; + } + } + + PyDict_SetItem(cls->tp_dict, k__descriptors, field_descriptors); + + // Enum Values + ScopedPyObjectPtr enum_types(PyObject_GetAttrString(descriptor, + "enum_types")); + if (enum_types == NULL) { + return NULL; + } + ScopedPyObjectPtr type_iter(PyObject_GetIter(enum_types)); + if (type_iter == NULL) { + return NULL; + } + ScopedPyObjectPtr enum_type; + while ((enum_type.reset(PyIter_Next(type_iter))) != NULL) { + ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs( + EnumTypeWrapper_class, enum_type.get(), NULL)); + if (wrapped == NULL) { + return NULL; + } + ScopedPyObjectPtr enum_name(PyObject_GetAttr(enum_type, kname)); + if (enum_name == NULL) { + return NULL; + } + if (PyObject_SetAttr(reinterpret_cast(cls), + enum_name, wrapped) == -1) { + return NULL; + } + + ScopedPyObjectPtr enum_values(PyObject_GetAttrString(enum_type, "values")); + if (enum_values == NULL) { + return NULL; + } + ScopedPyObjectPtr values_iter(PyObject_GetIter(enum_values)); + if (values_iter == NULL) { + return NULL; + } + ScopedPyObjectPtr enum_value; + while ((enum_value.reset(PyIter_Next(values_iter))) != NULL) { + ScopedPyObjectPtr value_name(PyObject_GetAttr(enum_value, kname)); + if (value_name == NULL) { + return NULL; + } + ScopedPyObjectPtr value_number(PyObject_GetAttrString(enum_value, + "number")); + if (value_number == NULL) { + return NULL; + } + if (PyObject_SetAttr(reinterpret_cast(cls), + value_name, value_number) == -1) { + return NULL; + } + } + if (PyErr_Occurred()) { // If PyIter_Next failed + return NULL; + } + } + if (PyErr_Occurred()) { // If PyIter_Next failed + return NULL; + } + + ScopedPyObjectPtr extension_dict( + PyObject_GetAttr(descriptor, kextensions_by_name)); + if (extension_dict == NULL || !PyDict_Check(extension_dict)) { + PyErr_SetString(PyExc_TypeError, "extensions_by_name not a dict"); + return NULL; + } + Py_ssize_t pos = 0; + PyObject* extension_name; + PyObject* extension_field; + + while (PyDict_Next(extension_dict, &pos, &extension_name, &extension_field)) { + if (PyObject_SetAttr(reinterpret_cast(cls), + extension_name, extension_field) == -1) { + return NULL; + } + ScopedPyObjectPtr py_cfield_descriptor( + PyObject_GetAttrString(extension_field, "_cdescriptor")); + if (py_cfield_descriptor == NULL) { + return NULL; + } + CFieldDescriptor* cfield_descriptor = + reinterpret_cast(py_cfield_descriptor.get()); + Py_INCREF(extension_field); + cfield_descriptor->descriptor_field = extension_field; + + ScopedPyObjectPtr field_name_upcased( + PyObject_CallMethod(extension_name, "upper", NULL)); + if (field_name_upcased == NULL) { + return NULL; + } + ScopedPyObjectPtr field_number_name(PyObject_CallMethod( + field_name_upcased, "__add__", "(O)", _NUMBER_string.get())); + if (field_number_name == NULL) { + return NULL; + } + ScopedPyObjectPtr number(PyInt_FromLong( + cfield_descriptor->descriptor->number())); + if (number == NULL) { + return NULL; + } + if (PyObject_SetAttr(reinterpret_cast(cls), + field_number_name, PyInt_FromLong( + cfield_descriptor->descriptor->number())) == -1) { + return NULL; + } + } + + Py_RETURN_NONE; +} + +PyObject* DeepCopy(CMessage* self, PyObject* arg) { + PyObject* clone = PyObject_CallObject( + reinterpret_cast(Py_TYPE(self)), NULL); + if (clone == NULL) { + return NULL; + } + if (!PyObject_TypeCheck(clone, &CMessage_Type)) { + Py_DECREF(clone); + return NULL; + } + if (InitAttributes(reinterpret_cast(clone), NULL, NULL) < 0) { + Py_DECREF(clone); + return NULL; + } + if (MergeFrom(reinterpret_cast(clone), + reinterpret_cast(self)) == NULL) { + Py_DECREF(clone); + return NULL; + } + return clone; +} + +PyObject* ToUnicode(CMessage* self) { + // Lazy import to prevent circular dependencies + ScopedPyObjectPtr text_format( + PyImport_ImportModule("google.protobuf.text_format")); + if (text_format == NULL) { + return NULL; + } + ScopedPyObjectPtr method_name(PyString_FromString("MessageToString")); + if (method_name == NULL) { + return NULL; + } + Py_INCREF(Py_True); + ScopedPyObjectPtr encoded(PyObject_CallMethodObjArgs(text_format, method_name, + self, Py_True, NULL)); + Py_DECREF(Py_True); + if (encoded == NULL) { + return NULL; + } +#if PY_MAJOR_VERSION < 3 + PyObject* decoded = PyString_AsDecodedObject(encoded, "utf-8", NULL); +#else + PyObject* decoded = PyUnicode_FromEncodedObject(encoded, "utf-8", NULL); +#endif + if (decoded == NULL) { + return NULL; + } + return decoded; +} + +PyObject* Reduce(CMessage* self) { + ScopedPyObjectPtr constructor(reinterpret_cast(Py_TYPE(self))); + constructor.inc(); + ScopedPyObjectPtr args(PyTuple_New(0)); + if (args == NULL) { + return NULL; + } + ScopedPyObjectPtr state(PyDict_New()); + if (state == NULL) { + return NULL; + } + ScopedPyObjectPtr serialized(SerializePartialToString(self)); + if (serialized == NULL) { + return NULL; + } + if (PyDict_SetItemString(state, "serialized", serialized) < 0) { + return NULL; + } + return Py_BuildValue("OOO", constructor.get(), args.get(), state.get()); +} + +PyObject* SetState(CMessage* self, PyObject* state) { + if (!PyDict_Check(state)) { + PyErr_SetString(PyExc_TypeError, "state not a dict"); + return NULL; + } + PyObject* serialized = PyDict_GetItemString(state, "serialized"); + if (serialized == NULL) { + return NULL; + } + if (ParseFromString(self, serialized) == NULL) { + return NULL; + } + Py_RETURN_NONE; +} + +// CMessage static methods: +PyObject* _GetFieldDescriptor(PyObject* unused, PyObject* arg) { + return cdescriptor_pool::FindFieldByName(descriptor_pool, arg); +} + +PyObject* _GetExtensionDescriptor(PyObject* unused, PyObject* arg) { + return cdescriptor_pool::FindExtensionByName(descriptor_pool, arg); +} + +static PyMemberDef Members[] = { + {"Extensions", T_OBJECT_EX, offsetof(CMessage, extensions), 0, + "Extension dict"}, + {NULL} +}; + +static PyMethodDef Methods[] = { + { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, + "Makes a deep copy of the class." }, + { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, + "Outputs picklable representation of the message." }, + { "__setstate__", (PyCFunction)SetState, METH_O, + "Inputs picklable representation of the message." }, + { "__unicode__", (PyCFunction)ToUnicode, METH_NOARGS, + "Outputs a unicode representation of the message." }, + { "AddDescriptors", (PyCFunction)AddDescriptors, METH_O | METH_CLASS, + "Adds field descriptors to the class" }, + { "ByteSize", (PyCFunction)ByteSize, METH_NOARGS, + "Returns the size of the message in bytes." }, + { "Clear", (PyCFunction)Clear, METH_NOARGS, + "Clears the message." }, + { "ClearExtension", (PyCFunction)ClearExtension, METH_O, + "Clears a message field." }, + { "ClearField", (PyCFunction)ClearField, METH_O, + "Clears a message field." }, + { "CopyFrom", (PyCFunction)CopyFrom, METH_O, + "Copies a protocol message into the current message." }, + { "FindInitializationErrors", (PyCFunction)FindInitializationErrors, + METH_NOARGS, + "Finds unset required fields." }, + { "FromString", (PyCFunction)FromString, METH_O | METH_CLASS, + "Creates new method instance from given serialized data." }, + { "HasExtension", (PyCFunction)HasExtension, METH_O, + "Checks if a message field is set." }, + { "HasField", (PyCFunction)HasField, METH_O, + "Checks if a message field is set." }, + { "IsInitialized", (PyCFunction)IsInitialized, METH_VARARGS, + "Checks if all required fields of a protocol message are set." }, + { "ListFields", (PyCFunction)ListFields, METH_NOARGS, + "Lists all set fields of a message." }, + { "MergeFrom", (PyCFunction)MergeFrom, METH_O, + "Merges a protocol message into the current message." }, + { "MergeFromString", (PyCFunction)MergeFromString, METH_O, + "Merges a serialized message into the current message." }, + { "ParseFromString", (PyCFunction)ParseFromString, METH_O, + "Parses a serialized message into the current message." }, + { "RegisterExtension", (PyCFunction)RegisterExtension, METH_O | METH_CLASS, + "Registers an extension with the current message." }, + { "SerializePartialToString", (PyCFunction)SerializePartialToString, + METH_NOARGS, + "Serializes the message to a string, even if it isn't initialized." }, + { "SerializeToString", (PyCFunction)SerializeToString, METH_NOARGS, + "Serializes the message to a string, only for initialized messages." }, + { "SetInParent", (PyCFunction)SetInParent, METH_NOARGS, + "Sets the has bit of the given field in its parent message." }, + { "WhichOneof", (PyCFunction)WhichOneof, METH_O, + "Returns the name of the field set inside a oneof, " + "or None if no field is set." }, + + // Static Methods. + { "_BuildFile", (PyCFunction)Python_BuildFile, METH_O | METH_STATIC, + "Registers a new protocol buffer file in the global C++ descriptor pool." }, + { "_GetFieldDescriptor", (PyCFunction)_GetFieldDescriptor, + METH_O | METH_STATIC, "Finds a field descriptor in the message pool." }, + { "_GetExtensionDescriptor", (PyCFunction)_GetExtensionDescriptor, + METH_O | METH_STATIC, + "Finds a extension descriptor in the message pool." }, + { NULL, NULL} +}; + +PyObject* GetAttr(CMessage* self, PyObject* name) { + PyObject* value = PyDict_GetItem(self->composite_fields, name); + if (value != NULL) { + Py_INCREF(value); + return value; + } + + PyObject* descriptor = GetDescriptor(self, name); + if (descriptor != NULL) { + CFieldDescriptor* cdescriptor = + reinterpret_cast(descriptor); + const google::protobuf::FieldDescriptor* field_descriptor = cdescriptor->descriptor; + if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { + if (field_descriptor->cpp_type() == + google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + PyObject* py_container = PyObject_CallObject( + reinterpret_cast(&RepeatedCompositeContainer_Type), + NULL); + if (py_container == NULL) { + return NULL; + } + RepeatedCompositeContainer* container = + reinterpret_cast(py_container); + PyObject* field = cdescriptor->descriptor_field; + PyObject* message_type = PyObject_GetAttr(field, kmessage_type); + if (message_type == NULL) { + return NULL; + } + PyObject* concrete_class = + PyObject_GetAttr(message_type, k_concrete_class); + if (concrete_class == NULL) { + return NULL; + } + container->parent = self; + container->parent_field = cdescriptor; + container->message = self->message; + container->owner = self->owner; + container->subclass_init = concrete_class; + Py_DECREF(message_type); + if (PyDict_SetItem(self->composite_fields, name, py_container) < 0) { + Py_DECREF(py_container); + return NULL; + } + return py_container; + } else { + ScopedPyObjectPtr init_args(PyTuple_Pack(2, self, cdescriptor)); + PyObject* py_container = PyObject_CallObject( + reinterpret_cast(&RepeatedScalarContainer_Type), + init_args); + if (py_container == NULL) { + return NULL; + } + if (PyDict_SetItem(self->composite_fields, name, py_container) < 0) { + Py_DECREF(py_container); + return NULL; + } + return py_container; + } + } else { + if (field_descriptor->cpp_type() == + google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + PyObject* sub_message = InternalGetSubMessage(self, cdescriptor); + if (PyDict_SetItem(self->composite_fields, name, sub_message) < 0) { + Py_DECREF(sub_message); + return NULL; + } + return sub_message; + } else { + return InternalGetScalar(self, field_descriptor); + } + } + } + + return CMessage_Type.tp_base->tp_getattro(reinterpret_cast(self), + name); +} + +int SetAttr(CMessage* self, PyObject* name, PyObject* value) { + if (PyDict_Contains(self->composite_fields, name)) { + PyErr_SetString(PyExc_TypeError, "Can't set composite field"); + return -1; + } + + PyObject* descriptor = GetDescriptor(self, name); + if (descriptor != NULL) { + AssureWritable(self); + CFieldDescriptor* cdescriptor = + reinterpret_cast(descriptor); + const google::protobuf::FieldDescriptor* field_descriptor = cdescriptor->descriptor; + if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { + PyErr_Format(PyExc_AttributeError, "Assignment not allowed to repeated " + "field \"%s\" in protocol message object.", + field_descriptor->name().c_str()); + return -1; + } else { + if (field_descriptor->cpp_type() == + google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + PyErr_Format(PyExc_AttributeError, "Assignment not allowed to " + "field \"%s\" in protocol message object.", + field_descriptor->name().c_str()); + return -1; + } else { + return InternalSetScalar(self, field_descriptor, value); + } + } + } + + PyErr_Format(PyExc_AttributeError, "Assignment not allowed"); + return -1; +} + +} // namespace cmessage + +PyTypeObject CMessage_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "google.protobuf.internal." + "cpp._message.CMessage", // tp_name + sizeof(CMessage), // tp_basicsize + 0, // tp_itemsize + (destructor)cmessage::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + (reprfunc)cmessage::ToStr, // tp_str + (getattrofunc)cmessage::GetAttr, // tp_getattro + (setattrofunc)cmessage::SetAttr, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags + "A ProtocolMessage", // tp_doc + 0, // tp_traverse + 0, // tp_clear + (richcmpfunc)cmessage::RichCompare, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + cmessage::Methods, // tp_methods + cmessage::Members, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + (initproc)cmessage::Init, // tp_init + 0, // tp_alloc + cmessage::New, // tp_new +}; + +// --- Exposing the C proto living inside Python proto to C code: + +const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg); +Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg); + +static const google::protobuf::Message* GetCProtoInsidePyProtoImpl(PyObject* msg) { + if (!PyObject_TypeCheck(msg, &CMessage_Type)) { + return NULL; + } + CMessage* cmsg = reinterpret_cast(msg); + return cmsg->message; +} + +static google::protobuf::Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) { + if (!PyObject_TypeCheck(msg, &CMessage_Type)) { + return NULL; + } + CMessage* cmsg = reinterpret_cast(msg); + if (PyDict_Size(cmsg->composite_fields) != 0 || + (cmsg->extensions != NULL && + PyDict_Size(cmsg->extensions->values) != 0)) { + // There is currently no way of accurately syncing arbitrary changes to + // the underlying C++ message back to the CMessage (e.g. removed repeated + // composite containers). We only allow direct mutation of the underlying + // C++ message if there is no child data in the CMessage. + return NULL; + } + cmessage::AssureWritable(cmsg); + return cmsg->message; +} + +static const char module_docstring[] = +"python-proto2 is a module that can be used to enhance proto2 Python API\n" +"performance.\n" +"\n" +"It provides access to the protocol buffers C++ reflection API that\n" +"implements the basic protocol buffer functions."; + +void InitGlobals() { + // TODO(gps): Check all return values in this function for NULL and propagate + // the error (MemoryError) on up to result in an import failure. These should + // also be freed and reset to NULL during finalization. + kPythonZero = PyInt_FromLong(0); + kint32min_py = PyInt_FromLong(kint32min); + kint32max_py = PyInt_FromLong(kint32max); + kuint32max_py = PyLong_FromLongLong(kuint32max); + kint64min_py = PyLong_FromLongLong(kint64min); + kint64max_py = PyLong_FromLongLong(kint64max); + kuint64max_py = PyLong_FromUnsignedLongLong(kuint64max); + + kDESCRIPTOR = PyString_FromString("DESCRIPTOR"); + k__descriptors = PyString_FromString("__descriptors"); + kfull_name = PyString_FromString("full_name"); + kis_extendable = PyString_FromString("is_extendable"); + kextensions_by_name = PyString_FromString("extensions_by_name"); + k_extensions_by_name = PyString_FromString("_extensions_by_name"); + k_extensions_by_number = PyString_FromString("_extensions_by_number"); + k_concrete_class = PyString_FromString("_concrete_class"); + kmessage_type = PyString_FromString("message_type"); + kname = PyString_FromString("name"); + kfields_by_name = PyString_FromString("fields_by_name"); + + global_message_factory = new DynamicMessageFactory(GetDescriptorPool()); + global_message_factory->SetDelegateToGeneratedFactory(true); + + descriptor_pool = reinterpret_cast( + Python_NewCDescriptorPool(NULL, NULL)); +} + +bool InitProto2MessageModule(PyObject *m) { + InitGlobals(); + + google::protobuf::python::CMessage_Type.tp_hash = PyObject_HashNotImplemented; + if (PyType_Ready(&google::protobuf::python::CMessage_Type) < 0) { + return false; + } + + // All three of these are actually set elsewhere, directly onto the child + // protocol buffer message class, but set them here as well to document that + // subclasses need to set these. + PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict, kDESCRIPTOR, Py_None); + PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict, + k_extensions_by_name, Py_None); + PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict, + k_extensions_by_number, Py_None); + + PyModule_AddObject(m, "Message", reinterpret_cast( + &google::protobuf::python::CMessage_Type)); + + google::protobuf::python::RepeatedScalarContainer_Type.tp_new = PyType_GenericNew; + google::protobuf::python::RepeatedScalarContainer_Type.tp_hash = + PyObject_HashNotImplemented; + if (PyType_Ready(&google::protobuf::python::RepeatedScalarContainer_Type) < 0) { + return false; + } + + PyModule_AddObject(m, "RepeatedScalarContainer", + reinterpret_cast( + &google::protobuf::python::RepeatedScalarContainer_Type)); + + google::protobuf::python::RepeatedCompositeContainer_Type.tp_new = PyType_GenericNew; + google::protobuf::python::RepeatedCompositeContainer_Type.tp_hash = + PyObject_HashNotImplemented; + if (PyType_Ready(&google::protobuf::python::RepeatedCompositeContainer_Type) < 0) { + return false; + } + + PyModule_AddObject( + m, "RepeatedCompositeContainer", + reinterpret_cast( + &google::protobuf::python::RepeatedCompositeContainer_Type)); + + google::protobuf::python::ExtensionDict_Type.tp_new = PyType_GenericNew; + google::protobuf::python::ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented; + if (PyType_Ready(&google::protobuf::python::ExtensionDict_Type) < 0) { + return false; + } + + PyModule_AddObject( + m, "ExtensionDict", + reinterpret_cast(&google::protobuf::python::ExtensionDict_Type)); + + if (!google::protobuf::python::InitDescriptor()) { + return false; + } + + PyObject* enum_type_wrapper = PyImport_ImportModule( + "google.protobuf.internal.enum_type_wrapper"); + if (enum_type_wrapper == NULL) { + return false; + } + google::protobuf::python::EnumTypeWrapper_class = + PyObject_GetAttrString(enum_type_wrapper, "EnumTypeWrapper"); + Py_DECREF(enum_type_wrapper); + + PyObject* message_module = PyImport_ImportModule( + "google.protobuf.message"); + if (message_module == NULL) { + return false; + } + google::protobuf::python::EncodeError_class = PyObject_GetAttrString(message_module, + "EncodeError"); + google::protobuf::python::DecodeError_class = PyObject_GetAttrString(message_module, + "DecodeError"); + Py_DECREF(message_module); + + PyObject* pickle_module = PyImport_ImportModule("pickle"); + if (pickle_module == NULL) { + return false; + } + google::protobuf::python::PickleError_class = PyObject_GetAttrString(pickle_module, + "PickleError"); + Py_DECREF(pickle_module); + + // Override {Get,Mutable}CProtoInsidePyProto. + google::protobuf::python::GetCProtoInsidePyProtoPtr = + google::protobuf::python::GetCProtoInsidePyProtoImpl; + google::protobuf::python::MutableCProtoInsidePyProtoPtr = + google::protobuf::python::MutableCProtoInsidePyProtoImpl; + + return true; +} + +} // namespace python +} // namespace protobuf + + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef _module = { + PyModuleDef_HEAD_INIT, + "_message", + google::protobuf::python::module_docstring, + -1, + NULL, + NULL, + NULL, + NULL, + NULL +}; +#define INITFUNC PyInit__message +#define INITFUNC_ERRORVAL NULL +#else // Python 2 +#define INITFUNC init_message +#define INITFUNC_ERRORVAL +#endif + +extern "C" { + PyMODINIT_FUNC INITFUNC(void) { + PyObject* m; +#if PY_MAJOR_VERSION >= 3 + m = PyModule_Create(&_module); +#else + m = Py_InitModule3("_message", NULL, google::protobuf::python::module_docstring); +#endif + if (m == NULL) { + return INITFUNC_ERRORVAL; + } + + if (!google::protobuf::python::InitProto2MessageModule(m)) { + Py_DECREF(m); + return INITFUNC_ERRORVAL; + } + +#if PY_MAJOR_VERSION >= 3 + return m; +#endif + } +} +} // namespace google diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h new file mode 100644 index 0000000..28e504f --- /dev/null +++ b/python/google/protobuf/pyext/message.h @@ -0,0 +1,305 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: anuraag@google.com (Anuraag Agrawal) +// Author: tibell@google.com (Johan Tibell) + +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__ + +#include + +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include + + +namespace google { +namespace protobuf { + +class Message; +class Reflection; +class FieldDescriptor; + +using internal::shared_ptr; + +namespace python { + +struct CFieldDescriptor; +struct ExtensionDict; + +typedef struct CMessage { + PyObject_HEAD; + + // This is the top-level C++ Message object that owns the whole + // proto tree. Every Python CMessage holds a reference to it in + // order to keep it alive as long as there's a Python object that + // references any part of the tree. + shared_ptr owner; + + // Weak reference to a parent CMessage object. This is NULL for any top-level + // message and is set for any child message (i.e. a child submessage or a + // part of a repeated composite field). + // + // Used to make sure all ancestors are also mutable when first modifying + // a child submessage (in other words, turning a default message instance + // into a mutable one). + // + // If a submessage is released (becomes a new top-level message), this field + // MUST be set to NULL. The parent may get deallocated and further attempts + // to use this pointer will result in a crash. + struct CMessage* parent; + + // Weak reference to the parent's descriptor that describes this submessage. + // Used together with the parent's message when making a default message + // instance mutable. + // TODO(anuraag): With a bit of work on the Python/C++ layer, it should be + // possible to make this a direct pointer to a C++ FieldDescriptor, this would + // be easier if this implementation replaces upstream. + CFieldDescriptor* parent_field; + + // Pointer to the C++ Message object for this CMessage. The + // CMessage does not own this pointer. + Message* message; + + // Indicates this submessage is pointing to a default instance of a message. + // Submessages are always first created as read only messages and are then + // made writable, at which point this field is set to false. + bool read_only; + + // A reference to a Python dictionary containing CMessage, + // RepeatedCompositeContainer, and RepeatedScalarContainer + // objects. Used as a cache to make sure we don't have to make a + // Python wrapper for the C++ Message objects on every access, or + // deal with the synchronization nightmare that could create. + PyObject* composite_fields; + + // A reference to the dictionary containing the message's extensions. + // Similar to composite_fields, acting as a cache, but also contains the + // required extension dict logic. + ExtensionDict* extensions; +} CMessage; + +extern PyTypeObject CMessage_Type; + +namespace cmessage { + +// Create a new empty message that can be populated by the parent. +PyObject* NewEmpty(PyObject* type); + +// Release a submessage from its proto tree, making it a new top-level messgae. +// A new message will be created if this is a read-only default instance. +// +// Corresponds to reflection api method ReleaseMessage. +int ReleaseSubMessage(google::protobuf::Message* message, + const google::protobuf::FieldDescriptor* field_descriptor, + CMessage* child_cmessage); + +// Initializes a new CMessage instance for a submessage. Only called once per +// submessage as the result is cached in composite_fields. +// +// Corresponds to reflection api method GetMessage. +PyObject* InternalGetSubMessage(CMessage* self, + CFieldDescriptor* cfield_descriptor); + +// Deletes a range of C++ submessages in a repeated field (following a +// removal in a RepeatedCompositeContainer). +// +// Releases messages to the provided cmessage_list if it is not NULL rather +// than just removing them from the underlying proto. This cmessage_list must +// have a CMessage for each underlying submessage. The CMessages refered to +// by slice will be removed from cmessage_list by this function. +// +// Corresponds to reflection api method RemoveLast. +int InternalDeleteRepeatedField(google::protobuf::Message* message, + const google::protobuf::FieldDescriptor* field_descriptor, + PyObject* slice, PyObject* cmessage_list); + +// Sets the specified scalar value to the message. +int InternalSetScalar(CMessage* self, + const google::protobuf::FieldDescriptor* field_descriptor, + PyObject* value); + +// Retrieves the specified scalar value from the message. +// +// Returns a new python reference. +PyObject* InternalGetScalar(CMessage* self, + const google::protobuf::FieldDescriptor* field_descriptor); + +// Clears the message, removing all contained data. Extension dictionary and +// submessages are released first if there are remaining external references. +// +// Corresponds to message api method Clear. +PyObject* Clear(CMessage* self); + +// Clears the data described by the given descriptor. Used to clear extensions +// (which don't have names). Extension release is handled by ExtensionDict +// class, not this function. +// TODO(anuraag): Try to make this discrepancy in release semantics with +// ClearField less confusing. +// +// Corresponds to reflection api method ClearField. +PyObject* ClearFieldByDescriptor( + CMessage* self, + const google::protobuf::FieldDescriptor* descriptor); + +// Clears the data for the given field name. The message is released if there +// are any external references. +// +// Corresponds to reflection api method ClearField. +PyObject* ClearField(CMessage* self, PyObject* arg); + +// Checks if the message has the field described by the descriptor. Used for +// extensions (which have no name). +// +// Corresponds to reflection api method HasField +PyObject* HasFieldByDescriptor( + CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor); + +// Checks if the message has the named field. +// +// Corresponds to reflection api method HasField. +PyObject* HasField(CMessage* self, PyObject* arg); + +// Initializes constants/enum values on a message. This is called by +// RepeatedCompositeContainer and ExtensionDict after calling the constructor. +// TODO(anuraag): Make it always called from within the constructor since it can +int InitAttributes(CMessage* self, PyObject* descriptor, PyObject* kwargs); + +PyObject* MergeFrom(CMessage* self, PyObject* arg); + +// Retrieves an attribute named 'name' from CMessage 'self'. Returns +// the attribute value on success, or NULL on failure. +// +// Returns a new reference. +PyObject* GetAttr(CMessage* self, PyObject* name); + +// Set the value of the attribute named 'name', for CMessage 'self', +// to the value 'value'. Returns -1 on failure. +int SetAttr(CMessage* self, PyObject* name, PyObject* value); + +PyObject* FindInitializationErrors(CMessage* self); + +// Set the owner field of self and any children of self, recursively. +// Used when self is being released and thus has a new owner (the +// released Message.) +int SetOwner(CMessage* self, const shared_ptr& new_owner); + +int AssureWritable(CMessage* self); + +} // namespace cmessage + +/* Is 64bit */ +#define IS_64BIT (SIZEOF_LONG == 8) + +#define FIELD_BELONGS_TO_MESSAGE(field_descriptor, message) \ + ((message)->GetDescriptor() == (field_descriptor)->containing_type()) + +#define FIELD_IS_REPEATED(field_descriptor) \ + ((field_descriptor)->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) + +#define GOOGLE_CHECK_GET_INT32(arg, value, err) \ + int32 value; \ + if (!CheckAndGetInteger(arg, &value, kint32min_py, kint32max_py)) { \ + return err; \ + } + +#define GOOGLE_CHECK_GET_INT64(arg, value, err) \ + int64 value; \ + if (!CheckAndGetInteger(arg, &value, kint64min_py, kint64max_py)) { \ + return err; \ + } + +#define GOOGLE_CHECK_GET_UINT32(arg, value, err) \ + uint32 value; \ + if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint32max_py)) { \ + return err; \ + } + +#define GOOGLE_CHECK_GET_UINT64(arg, value, err) \ + uint64 value; \ + if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint64max_py)) { \ + return err; \ + } + +#define GOOGLE_CHECK_GET_FLOAT(arg, value, err) \ + float value; \ + if (!CheckAndGetFloat(arg, &value)) { \ + return err; \ + } \ + +#define GOOGLE_CHECK_GET_DOUBLE(arg, value, err) \ + double value; \ + if (!CheckAndGetDouble(arg, &value)) { \ + return err; \ + } + +#define GOOGLE_CHECK_GET_BOOL(arg, value, err) \ + bool value; \ + if (!CheckAndGetBool(arg, &value)) { \ + return err; \ + } + + +extern PyObject* kPythonZero; +extern PyObject* kint32min_py; +extern PyObject* kint32max_py; +extern PyObject* kuint32max_py; +extern PyObject* kint64min_py; +extern PyObject* kint64max_py; +extern PyObject* kuint64max_py; + +#define C(str) const_cast(str) + +void FormatTypeError(PyObject* arg, char* expected_types); +template +bool CheckAndGetInteger( + PyObject* arg, T* value, PyObject* min, PyObject* max); +bool CheckAndGetDouble(PyObject* arg, double* value); +bool CheckAndGetFloat(PyObject* arg, float* value); +bool CheckAndGetBool(PyObject* arg, bool* value); +bool CheckAndSetString( + PyObject* arg, google::protobuf::Message* message, + const google::protobuf::FieldDescriptor* descriptor, + const google::protobuf::Reflection* reflection, + bool append, + int index); +PyObject* ToStringObject( + const google::protobuf::FieldDescriptor* descriptor, string value); + +extern PyObject* PickleError_class; + +} // namespace python +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__ diff --git a/python/google/protobuf/pyext/message_factory_cpp2_test.py b/python/google/protobuf/pyext/message_factory_cpp2_test.py new file mode 100644 index 0000000..fb52e1b --- /dev/null +++ b/python/google/protobuf/pyext/message_factory_cpp2_test.py @@ -0,0 +1,56 @@ +#! /usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Tests for google.protobuf.message_factory.""" + +import os +os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' +os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2' + +# We must set the implementation version above before the google3 imports. +# pylint: disable=g-import-not-at-top +from google.apputils import basetest +from google.protobuf.internal import api_implementation +# Run all tests from the original module by putting them in our namespace. +# pylint: disable=wildcard-import +from google.protobuf.internal.message_factory_test import * + + +class ConfirmCppApi2Test(basetest.TestCase): + + def testImplementationSetting(self): + self.assertEqual('cpp', api_implementation.Type()) + self.assertEqual(2, api_implementation.Version()) + + +if __name__ == '__main__': + basetest.main() diff --git a/python/google/protobuf/pyext/proto2_api_test.proto b/python/google/protobuf/pyext/proto2_api_test.proto new file mode 100644 index 0000000..eef9b73 --- /dev/null +++ b/python/google/protobuf/pyext/proto2_api_test.proto @@ -0,0 +1,38 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import "google/protobuf/internal/cpp/proto1_api_test.proto"; + +package google.protobuf.python.internal; + +message TestNestedProto1APIMessage { + optional int32 a = 1; + optional TestMessage.NestedMessage b = 2; +} diff --git a/python/google/protobuf/pyext/python.proto b/python/google/protobuf/pyext/python.proto new file mode 100644 index 0000000..ee6d5ab --- /dev/null +++ b/python/google/protobuf/pyext/python.proto @@ -0,0 +1,66 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: tibell@google.com (Johan Tibell) +// +// These message definitions are used to exercises known corner cases +// in the C++ implementation of the Python API. + + +package google.protobuf.python.internal; + +// Protos optimized for SPEED use a strict superset of the generated code +// of equivalent ones optimized for CODE_SIZE, so we should optimize all our +// tests for speed unless explicitly testing code size optimization. +option optimize_for = SPEED; + +message TestAllTypes { + message NestedMessage { + optional int32 bb = 1; + optional ForeignMessage cc = 2; + } + + repeated NestedMessage repeated_nested_message = 1; + optional NestedMessage optional_nested_message = 2; + optional int32 optional_int32 = 3; +} + +message ForeignMessage { + optional int32 c = 1; + repeated int32 d = 2; +} + +message TestAllExtensions { + extensions 1 to max; +} + +extend TestAllExtensions { + optional TestAllTypes.NestedMessage optional_nested_message_extension = 1; +} diff --git a/python/google/protobuf/pyext/python_protobuf.h b/python/google/protobuf/pyext/python_protobuf.h new file mode 100644 index 0000000..c5b0b1c --- /dev/null +++ b/python/google/protobuf/pyext/python_protobuf.h @@ -0,0 +1,57 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: qrczak@google.com (Marcin Kowalczyk) +// +// This module exposes the C proto inside the given Python proto, in +// case the Python proto is implemented with a C proto. + +#ifndef GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__ +#define GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__ + +#include + +namespace google { +namespace protobuf { + +class Message; + +namespace python { + +// Return the pointer to the C proto inside the given Python proto, +// or NULL when this is not a Python proto implemented with a C proto. +const Message* GetCProtoInsidePyProto(PyObject* msg); +Message* MutableCProtoInsidePyProto(PyObject* msg); + +} // namespace python +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__ diff --git a/python/google/protobuf/pyext/reflection_cpp2_generated_test.py b/python/google/protobuf/pyext/reflection_cpp2_generated_test.py new file mode 100755 index 0000000..d7fce5f --- /dev/null +++ b/python/google/protobuf/pyext/reflection_cpp2_generated_test.py @@ -0,0 +1,94 @@ +#! /usr/bin/python +# -*- coding: utf-8 -*- +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Unittest for reflection.py, which tests the generated C++ implementation.""" + +__author__ = 'jasonh@google.com (Jason Hsueh)' + +import os +os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' +os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2' + +from google.apputils import basetest +from google.protobuf.internal import api_implementation +from google.protobuf.internal import more_extensions_dynamic_pb2 +from google.protobuf.internal import more_extensions_pb2 +from google.protobuf.internal.reflection_test import * + + +class ReflectionCppTest(basetest.TestCase): + def testImplementationSetting(self): + self.assertEqual('cpp', api_implementation.Type()) + self.assertEqual(2, api_implementation.Version()) + + def testExtensionOfGeneratedTypeInDynamicFile(self): + """Tests that a file built dynamically can extend a generated C++ type. + + The C++ implementation uses a DescriptorPool that has the generated + DescriptorPool as an underlay. Typically, a type can only find + extensions in its own pool. With the python C-extension, the generated C++ + extendee may be available, but not the extension. This tests that the + C-extension implements the correct special handling to make such extensions + available. + """ + pb1 = more_extensions_pb2.ExtendedMessage() + # Test that basic accessors work. + self.assertFalse( + pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension)) + self.assertFalse( + pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension)) + pb1.Extensions[more_extensions_dynamic_pb2.dynamic_int32_extension] = 17 + pb1.Extensions[more_extensions_dynamic_pb2.dynamic_message_extension].a = 24 + self.assertTrue( + pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension)) + self.assertTrue( + pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension)) + + # Now serialize the data and parse to a new message. + pb2 = more_extensions_pb2.ExtendedMessage() + pb2.MergeFromString(pb1.SerializeToString()) + + self.assertTrue( + pb2.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension)) + self.assertTrue( + pb2.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension)) + self.assertEqual( + 17, pb2.Extensions[more_extensions_dynamic_pb2.dynamic_int32_extension]) + self.assertEqual( + 24, + pb2.Extensions[more_extensions_dynamic_pb2.dynamic_message_extension].a) + + + +if __name__ == '__main__': + basetest.main() diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc new file mode 100644 index 0000000..b164505 --- /dev/null +++ b/python/google/protobuf/pyext/repeated_composite_container.cc @@ -0,0 +1,763 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: anuraag@google.com (Anuraag Agrawal) +// Author: tibell@google.com (Johan Tibell) + +#include + +#include +#ifndef _SHARED_PTR_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#if PY_MAJOR_VERSION >= 3 + #define PyInt_Check PyLong_Check + #define PyInt_AsLong PyLong_AsLong + #define PyInt_FromLong PyLong_FromLong +#endif + +namespace google { +namespace protobuf { +namespace python { + +extern google::protobuf::DynamicMessageFactory* global_message_factory; + +namespace repeated_composite_container { + +// TODO(tibell): We might also want to check: +// GOOGLE_CHECK_NOTNULL((self)->owner.get()); +#define GOOGLE_CHECK_ATTACHED(self) \ + do { \ + GOOGLE_CHECK_NOTNULL((self)->message); \ + GOOGLE_CHECK_NOTNULL((self)->parent_field); \ + } while (0); + +#define GOOGLE_CHECK_RELEASED(self) \ + do { \ + GOOGLE_CHECK((self)->owner.get() == NULL); \ + GOOGLE_CHECK((self)->message == NULL); \ + GOOGLE_CHECK((self)->parent_field == NULL); \ + GOOGLE_CHECK((self)->parent == NULL); \ + } while (0); + +// Returns a new reference. +static PyObject* GetKey(PyObject* x) { + // Just the identity function. + Py_INCREF(x); + return x; +} + +#define GET_KEY(keyfunc, value) \ + ((keyfunc) == NULL ? \ + GetKey((value)) : \ + PyObject_CallFunctionObjArgs((keyfunc), (value), NULL)) + +// Converts a comparison function that returns -1, 0, or 1 into a +// less-than predicate. +// +// Returns -1 on error, 1 if x < y, 0 if x >= y. +static int islt(PyObject *x, PyObject *y, PyObject *compare) { + if (compare == NULL) + return PyObject_RichCompareBool(x, y, Py_LT); + + ScopedPyObjectPtr res(PyObject_CallFunctionObjArgs(compare, x, y, NULL)); + if (res == NULL) + return -1; + if (!PyInt_Check(res)) { + PyErr_Format(PyExc_TypeError, + "comparison function must return int, not %.200s", + Py_TYPE(res)->tp_name); + return -1; + } + return PyInt_AsLong(res) < 0; +} + +// Copied from uarrsort.c but swaps memcpy swaps with protobuf/python swaps +// TODO(anuraag): Is there a better way to do this then reinventing the wheel? +static int InternalQuickSort(RepeatedCompositeContainer* self, + Py_ssize_t start, + Py_ssize_t limit, + PyObject* cmp, + PyObject* keyfunc) { + if (limit - start <= 1) + return 0; // Nothing to sort. + + GOOGLE_CHECK_ATTACHED(self); + + google::protobuf::Message* message = self->message; + const google::protobuf::Reflection* reflection = message->GetReflection(); + const google::protobuf::FieldDescriptor* descriptor = self->parent_field->descriptor; + Py_ssize_t left; + Py_ssize_t right; + + PyObject* children = self->child_messages; + + do { + left = start; + right = limit; + ScopedPyObjectPtr mid( + GET_KEY(keyfunc, PyList_GET_ITEM(children, (start + limit) / 2))); + do { + ScopedPyObjectPtr key(GET_KEY(keyfunc, PyList_GET_ITEM(children, left))); + int is_lt = islt(key, mid, cmp); + if (is_lt == -1) + return -1; + /* array[left]SwapElements(message, descriptor, left, right); + PyObject* tmp = PyList_GET_ITEM(children, left); + PyList_SET_ITEM(children, left, PyList_GET_ITEM(children, right)); + PyList_SET_ITEM(children, right, tmp); + } + ++left; + } + } while (left < right); + + if ((right - start) < (limit - left)) { + /* sort [start..right[ */ + if (start < (right - 1)) { + InternalQuickSort(self, start, right, cmp, keyfunc); + } + + /* sort [left..limit[ */ + start = left; + } else { + /* sort [left..limit[ */ + if (left < (limit - 1)) { + InternalQuickSort(self, left, limit, cmp, keyfunc); + } + + /* sort [start..right[ */ + limit = right; + } + } while (start < (limit - 1)); + + return 0; +} + +#undef GET_KEY + +// --------------------------------------------------------------------- +// len() + +static Py_ssize_t Length(RepeatedCompositeContainer* self) { + google::protobuf::Message* message = self->message; + if (message != NULL) { + return message->GetReflection()->FieldSize(*message, + self->parent_field->descriptor); + } else { + // The container has been released (i.e. by a call to Clear() or + // ClearField() on the parent) and thus there's no message. + return PyList_GET_SIZE(self->child_messages); + } +} + +// Returns 0 if successful; returns -1 and sets an exception if +// unsuccessful. +static int UpdateChildMessages(RepeatedCompositeContainer* self) { + if (self->message == NULL) + return 0; + + // A MergeFrom on a parent message could have caused extra messages to be + // added in the underlying protobuf so add them to our list. They can never + // be removed in such a way so there's no need to worry about that. + Py_ssize_t message_length = Length(self); + Py_ssize_t child_length = PyList_GET_SIZE(self->child_messages); + google::protobuf::Message* message = self->message; + const google::protobuf::Reflection* reflection = message->GetReflection(); + for (Py_ssize_t i = child_length; i < message_length; ++i) { + const Message& sub_message = reflection->GetRepeatedMessage( + *(self->message), self->parent_field->descriptor, i); + ScopedPyObjectPtr py_cmsg(cmessage::NewEmpty(self->subclass_init)); + if (py_cmsg == NULL) { + return -1; + } + CMessage* cmsg = reinterpret_cast(py_cmsg.get()); + cmsg->owner = self->owner; + cmsg->message = const_cast(&sub_message); + cmsg->parent = self->parent; + if (cmessage::InitAttributes(cmsg, NULL, NULL) < 0) { + return -1; + } + PyList_Append(self->child_messages, py_cmsg); + } + return 0; +} + +// --------------------------------------------------------------------- +// add() + +static PyObject* AddToAttached(RepeatedCompositeContainer* self, + PyObject* args, + PyObject* kwargs) { + GOOGLE_CHECK_ATTACHED(self); + + if (UpdateChildMessages(self) < 0) { + return NULL; + } + if (cmessage::AssureWritable(self->parent) == -1) + return NULL; + google::protobuf::Message* message = self->message; + google::protobuf::Message* sub_message = + message->GetReflection()->AddMessage(message, + self->parent_field->descriptor); + PyObject* py_cmsg = cmessage::NewEmpty(self->subclass_init); + if (py_cmsg == NULL) { + return NULL; + } + CMessage* cmsg = reinterpret_cast(py_cmsg); + + cmsg->owner = self->owner; + cmsg->message = sub_message; + cmsg->parent = self->parent; + // cmessage::InitAttributes must be called after cmsg->message has + // been set. + if (cmessage::InitAttributes(cmsg, NULL, kwargs) < 0) { + Py_DECREF(py_cmsg); + return NULL; + } + PyList_Append(self->child_messages, py_cmsg); + return py_cmsg; +} + +static PyObject* AddToReleased(RepeatedCompositeContainer* self, + PyObject* args, + PyObject* kwargs) { + GOOGLE_CHECK_RELEASED(self); + + // Create the CMessage + PyObject* py_cmsg = PyObject_CallObject(self->subclass_init, NULL); + if (py_cmsg == NULL) + return NULL; + CMessage* cmsg = reinterpret_cast(py_cmsg); + if (cmessage::InitAttributes(cmsg, NULL, kwargs) < 0) { + Py_DECREF(py_cmsg); + return NULL; + } + + // The Message got created by the call to subclass_init above and + // it set self->owner to the newly allocated message. + + PyList_Append(self->child_messages, py_cmsg); + return py_cmsg; +} + +PyObject* Add(RepeatedCompositeContainer* self, + PyObject* args, + PyObject* kwargs) { + if (self->message == NULL) + return AddToReleased(self, args, kwargs); + else + return AddToAttached(self, args, kwargs); +} + +// --------------------------------------------------------------------- +// extend() + +PyObject* Extend(RepeatedCompositeContainer* self, PyObject* value) { + cmessage::AssureWritable(self->parent); + if (UpdateChildMessages(self) < 0) { + return NULL; + } + ScopedPyObjectPtr iter(PyObject_GetIter(value)); + if (iter == NULL) { + PyErr_SetString(PyExc_TypeError, "Value must be iterable"); + return NULL; + } + ScopedPyObjectPtr next; + while ((next.reset(PyIter_Next(iter))) != NULL) { + if (!PyObject_TypeCheck(next, &CMessage_Type)) { + PyErr_SetString(PyExc_TypeError, "Not a cmessage"); + return NULL; + } + ScopedPyObjectPtr new_message(Add(self, NULL, NULL)); + if (new_message == NULL) { + return NULL; + } + CMessage* new_cmessage = reinterpret_cast(new_message.get()); + if (cmessage::MergeFrom(new_cmessage, next) == NULL) { + return NULL; + } + } + if (PyErr_Occurred()) { + return NULL; + } + Py_RETURN_NONE; +} + +PyObject* MergeFrom(RepeatedCompositeContainer* self, PyObject* other) { + if (UpdateChildMessages(self) < 0) { + return NULL; + } + return Extend(self, other); +} + +PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice) { + if (UpdateChildMessages(self) < 0) { + return NULL; + } + Py_ssize_t from; + Py_ssize_t to; + Py_ssize_t step; + Py_ssize_t length = Length(self); + Py_ssize_t slicelength; + if (PySlice_Check(slice)) { +#if PY_MAJOR_VERSION >= 3 + if (PySlice_GetIndicesEx(slice, +#else + if (PySlice_GetIndicesEx(reinterpret_cast(slice), +#endif + length, &from, &to, &step, &slicelength) == -1) { + return NULL; + } + return PyList_GetSlice(self->child_messages, from, to); + } else if (PyInt_Check(slice) || PyLong_Check(slice)) { + from = to = PyLong_AsLong(slice); + if (from < 0) { + from = to = length + from; + } + PyObject* result = PyList_GetItem(self->child_messages, from); + if (result == NULL) { + return NULL; + } + Py_INCREF(result); + return result; + } + PyErr_SetString(PyExc_TypeError, "index must be an integer or slice"); + return NULL; +} + +int AssignSubscript(RepeatedCompositeContainer* self, + PyObject* slice, + PyObject* value) { + if (UpdateChildMessages(self) < 0) { + return -1; + } + if (value != NULL) { + PyErr_SetString(PyExc_TypeError, "does not support assignment"); + return -1; + } + + // Delete from the underlying Message, if any. + if (self->message != NULL) { + if (cmessage::InternalDeleteRepeatedField(self->message, + self->parent_field->descriptor, + slice, + self->child_messages) < 0) { + return -1; + } + } else { + Py_ssize_t from; + Py_ssize_t to; + Py_ssize_t step; + Py_ssize_t length = Length(self); + Py_ssize_t slicelength; + if (PySlice_Check(slice)) { +#if PY_MAJOR_VERSION >= 3 + if (PySlice_GetIndicesEx(slice, +#else + if (PySlice_GetIndicesEx(reinterpret_cast(slice), +#endif + length, &from, &to, &step, &slicelength) == -1) { + return -1; + } + return PySequence_DelSlice(self->child_messages, from, to); + } else if (PyInt_Check(slice) || PyLong_Check(slice)) { + from = to = PyLong_AsLong(slice); + if (from < 0) { + from = to = length + from; + } + return PySequence_DelItem(self->child_messages, from); + } + } + + return 0; +} + +static PyObject* Remove(RepeatedCompositeContainer* self, PyObject* value) { + if (UpdateChildMessages(self) < 0) { + return NULL; + } + Py_ssize_t index = PySequence_Index(self->child_messages, value); + if (index == -1) { + return NULL; + } + ScopedPyObjectPtr py_index(PyLong_FromLong(index)); + if (AssignSubscript(self, py_index, NULL) < 0) { + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject* RichCompare(RepeatedCompositeContainer* self, + PyObject* other, + int opid) { + if (UpdateChildMessages(self) < 0) { + return NULL; + } + if (!PyObject_TypeCheck(other, &RepeatedCompositeContainer_Type)) { + PyErr_SetString(PyExc_TypeError, + "Can only compare repeated composite fields " + "against other repeated composite fields."); + return NULL; + } + if (opid == Py_EQ || opid == Py_NE) { + // TODO(anuraag): Don't make new lists just for this... + ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); + if (full_slice == NULL) { + return NULL; + } + ScopedPyObjectPtr list(Subscript(self, full_slice)); + if (list == NULL) { + return NULL; + } + ScopedPyObjectPtr other_list( + Subscript( + reinterpret_cast(other), full_slice)); + if (other_list == NULL) { + return NULL; + } + return PyObject_RichCompare(list, other_list, opid); + } else { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } +} + +// --------------------------------------------------------------------- +// sort() + +static PyObject* SortAttached(RepeatedCompositeContainer* self, + PyObject* args, + PyObject* kwds) { + // Sort the underlying Message array. + PyObject *compare = NULL; + int reverse = 0; + PyObject *keyfunc = NULL; + static char *kwlist[] = {"cmp", "key", "reverse", 0}; + + if (args != NULL) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi:sort", + kwlist, &compare, &keyfunc, &reverse)) + return NULL; + } + if (compare == Py_None) + compare = NULL; + if (keyfunc == Py_None) + keyfunc = NULL; + + const Py_ssize_t length = Length(self); + if (InternalQuickSort(self, 0, length, compare, keyfunc) < 0) + return NULL; + + // Finally reverse the result if requested. + if (reverse) { + google::protobuf::Message* message = self->message; + const google::protobuf::Reflection* reflection = message->GetReflection(); + const google::protobuf::FieldDescriptor* descriptor = self->parent_field->descriptor; + + // Reverse the Message array. + for (int i = 0; i < length / 2; ++i) + reflection->SwapElements(message, descriptor, i, length - i - 1); + + // Reverse the Python list. + ScopedPyObjectPtr res(PyObject_CallMethod(self->child_messages, + "reverse", NULL)); + if (res == NULL) + return NULL; + } + + Py_RETURN_NONE; +} + +static PyObject* SortReleased(RepeatedCompositeContainer* self, + PyObject* args, + PyObject* kwds) { + ScopedPyObjectPtr m(PyObject_GetAttrString(self->child_messages, "sort")); + if (m == NULL) + return NULL; + if (PyObject_Call(m, args, kwds) == NULL) + return NULL; + Py_RETURN_NONE; +} + +static PyObject* Sort(RepeatedCompositeContainer* self, + PyObject* args, + PyObject* kwds) { + // Support the old sort_function argument for backwards + // compatibility. + if (kwds != NULL) { + PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function"); + if (sort_func != NULL) { + // Must set before deleting as sort_func is a borrowed reference + // and kwds might be the only thing keeping it alive. + PyDict_SetItemString(kwds, "cmp", sort_func); + PyDict_DelItemString(kwds, "sort_function"); + } + } + + if (UpdateChildMessages(self) < 0) + return NULL; + if (self->message == NULL) { + return SortReleased(self, args, kwds); + } else { + return SortAttached(self, args, kwds); + } +} + +// --------------------------------------------------------------------- + +static PyObject* Item(RepeatedCompositeContainer* self, Py_ssize_t index) { + if (UpdateChildMessages(self) < 0) { + return NULL; + } + Py_ssize_t length = Length(self); + if (index < 0) { + index = length + index; + } + PyObject* item = PyList_GetItem(self->child_messages, index); + if (item == NULL) { + return NULL; + } + Py_INCREF(item); + return item; +} + +// The caller takes ownership of the returned Message. +Message* ReleaseLast(const FieldDescriptor* field, + const Descriptor* type, + Message* message) { + GOOGLE_CHECK_NOTNULL(field); + GOOGLE_CHECK_NOTNULL(type); + GOOGLE_CHECK_NOTNULL(message); + + Message* released_message = message->GetReflection()->ReleaseLast( + message, field); + // TODO(tibell): Deal with proto1. + + // ReleaseMessage will return NULL which differs from + // child_cmessage->message, if the field does not exist. In this case, + // the latter points to the default instance via a const_cast<>, so we + // have to reset it to a new mutable object since we are taking ownership. + if (released_message == NULL) { + const Message* prototype = global_message_factory->GetPrototype(type); + GOOGLE_CHECK_NOTNULL(prototype); + return prototype->New(); + } else { + return released_message; + } +} + +// Release field of message and transfer the ownership to cmessage. +void ReleaseLastTo(const FieldDescriptor* field, + Message* message, + CMessage* cmessage) { + GOOGLE_CHECK_NOTNULL(field); + GOOGLE_CHECK_NOTNULL(message); + GOOGLE_CHECK_NOTNULL(cmessage); + + shared_ptr released_message( + ReleaseLast(field, cmessage->message->GetDescriptor(), message)); + cmessage->parent = NULL; + cmessage->parent_field = NULL; + cmessage->message = released_message.get(); + cmessage->read_only = false; + cmessage::SetOwner(cmessage, released_message); +} + +// Called to release a container using +// ClearField('container_field_name') on the parent. +int Release(RepeatedCompositeContainer* self) { + if (UpdateChildMessages(self) < 0) { + PyErr_WriteUnraisable(PyBytes_FromString("Failed to update released " + "messages")); + return -1; + } + + Message* message = self->message; + const FieldDescriptor* field = self->parent_field->descriptor; + + // The reflection API only lets us release the last message in a + // repeated field. Therefore we iterate through the children + // starting with the last one. + const Py_ssize_t size = PyList_GET_SIZE(self->child_messages); + GOOGLE_DCHECK_EQ(size, message->GetReflection()->FieldSize(*message, field)); + for (Py_ssize_t i = size - 1; i >= 0; --i) { + CMessage* child_cmessage = reinterpret_cast( + PyList_GET_ITEM(self->child_messages, i)); + ReleaseLastTo(field, message, child_cmessage); + } + + // Detach from containing message. + self->parent = NULL; + self->parent_field = NULL; + self->message = NULL; + self->owner.reset(); + + return 0; +} + +int SetOwner(RepeatedCompositeContainer* self, + const shared_ptr& new_owner) { + GOOGLE_CHECK_ATTACHED(self); + + self->owner = new_owner; + const Py_ssize_t n = PyList_GET_SIZE(self->child_messages); + for (Py_ssize_t i = 0; i < n; ++i) { + PyObject* msg = PyList_GET_ITEM(self->child_messages, i); + if (cmessage::SetOwner(reinterpret_cast(msg), new_owner) == -1) { + return -1; + } + } + return 0; +} + +static int Init(RepeatedCompositeContainer* self, + PyObject* args, + PyObject* kwargs) { + self->message = NULL; + self->parent = NULL; + self->parent_field = NULL; + self->subclass_init = NULL; + self->child_messages = PyList_New(0); + return 0; +} + +static void Dealloc(RepeatedCompositeContainer* self) { + Py_CLEAR(self->child_messages); + // TODO(tibell): Do we need to call delete on these objects to make + // sure their destructors are called? + self->owner.reset(); + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +static PySequenceMethods SqMethods = { + (lenfunc)Length, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + (ssizeargfunc)Item /* sq_item */ +}; + +static PyMappingMethods MpMethods = { + (lenfunc)Length, /* mp_length */ + (binaryfunc)Subscript, /* mp_subscript */ + (objobjargproc)AssignSubscript,/* mp_ass_subscript */ +}; + +static PyMethodDef Methods[] = { + { "add", (PyCFunction) Add, METH_VARARGS | METH_KEYWORDS, + "Adds an object to the repeated container." }, + { "extend", (PyCFunction) Extend, METH_O, + "Adds objects to the repeated container." }, + { "remove", (PyCFunction) Remove, METH_O, + "Removes an object from the repeated container." }, + { "sort", (PyCFunction) Sort, METH_VARARGS | METH_KEYWORDS, + "Sorts the repeated container." }, + { "MergeFrom", (PyCFunction) MergeFrom, METH_O, + "Adds objects to the repeated container." }, + { NULL, NULL } +}; + +} // namespace repeated_composite_container + +PyTypeObject RepeatedCompositeContainer_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "google.protobuf.internal." + "cpp._message.RepeatedCompositeContainer", // tp_name + sizeof(RepeatedCompositeContainer), // tp_basicsize + 0, // tp_itemsize + (destructor)repeated_composite_container::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &repeated_composite_container::SqMethods, // tp_as_sequence + &repeated_composite_container::MpMethods, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "A Repeated scalar container", // tp_doc + 0, // tp_traverse + 0, // tp_clear + (richcmpfunc)repeated_composite_container::RichCompare, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + repeated_composite_container::Methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + (initproc)repeated_composite_container::Init, // tp_init +}; + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h new file mode 100644 index 0000000..e8ed30e --- /dev/null +++ b/python/google/protobuf/pyext/repeated_composite_container.h @@ -0,0 +1,172 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: anuraag@google.com (Anuraag Agrawal) +// Author: tibell@google.com (Johan Tibell) + +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_COMPOSITE_CONTAINER_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_COMPOSITE_CONTAINER_H__ + +#include + +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include +#include + + +namespace google { +namespace protobuf { + +class FieldDescriptor; +class Message; + +using internal::shared_ptr; + +namespace python { + +struct CMessage; +struct CFieldDescriptor; + +// A RepeatedCompositeContainer can be in one of two states: attached +// or released. +// +// When in the attached state all modifications to the container are +// done both on the 'message' and on the 'child_messages' +// list. In this state all Messages refered to by the children in +// 'child_messages' are owner by the 'owner'. +// +// When in the released state 'message', 'owner', 'parent', and +// 'parent_field' are NULL. +typedef struct RepeatedCompositeContainer { + PyObject_HEAD; + + // This is the top-level C++ Message object that owns the whole + // proto tree. Every Python RepeatedCompositeContainer holds a + // reference to it in order to keep it alive as long as there's a + // Python object that references any part of the tree. + shared_ptr owner; + + // Weak reference to parent object. May be NULL. Used to make sure + // the parent is writable before modifying the + // RepeatedCompositeContainer. + CMessage* parent; + + // A descriptor used to modify the underlying 'message'. + CFieldDescriptor* parent_field; + + // Pointer to the C++ Message that contains this container. The + // RepeatedCompositeContainer does not own this pointer. + // + // If NULL, this message has been released from its parent (by + // calling Clear() or ClearField() on the parent. + Message* message; + + // A callable that is used to create new child messages. + PyObject* subclass_init; + + // A list of child messages. + PyObject* child_messages; +} RepeatedCompositeContainer; + +extern PyTypeObject RepeatedCompositeContainer_Type; + +namespace repeated_composite_container { + +// Returns the number of items in this repeated composite container. +static Py_ssize_t Length(RepeatedCompositeContainer* self); + +// Appends a new CMessage to the container and returns it. The +// CMessage is initialized using the content of kwargs. +// +// Returns a new reference if successful; returns NULL and sets an +// exception if unsuccessful. +PyObject* Add(RepeatedCompositeContainer* self, + PyObject* args, + PyObject* kwargs); + +// Appends all the CMessages in the input iterator to the container. +// +// Returns None if successful; returns NULL and sets an exception if +// unsuccessful. +PyObject* Extend(RepeatedCompositeContainer* self, PyObject* value); + +// Appends a new message to the container for each message in the +// input iterator, merging each data element in. Equivalent to extend. +// +// Returns None if successful; returns NULL and sets an exception if +// unsuccessful. +PyObject* MergeFrom(RepeatedCompositeContainer* self, PyObject* other); + +// Accesses messages in the container. +// +// Returns a new reference to the message for an integer parameter. +// Returns a new reference to a list of messages for a slice. +PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice); + +// Deletes items from the container (cannot be used for assignment). +// +// Returns 0 on success, -1 on failure. +int AssignSubscript(RepeatedCompositeContainer* self, + PyObject* slice, + PyObject* value); + +// Releases the messages in the container to the given message. +// +// Returns 0 on success, -1 on failure. +int ReleaseToMessage(RepeatedCompositeContainer* self, + google::protobuf::Message* new_message); + +// Releases the messages in the container to a new message. +// +// Returns 0 on success, -1 on failure. +int Release(RepeatedCompositeContainer* self); + +// Returns 0 on success, -1 on failure. +int SetOwner(RepeatedCompositeContainer* self, + const shared_ptr& new_owner); + +// Removes the last element of the repeated message field 'field' on +// the Message 'message', and transfers the ownership of the released +// Message to 'cmessage'. +// +// Corresponds to reflection api method ReleaseMessage. +void ReleaseLastTo(const FieldDescriptor* field, + Message* message, + CMessage* cmessage); + +} // namespace repeated_composite_container +} // namespace python +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_COMPOSITE_CONTAINER_H__ diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc new file mode 100644 index 0000000..b0fcd81 --- /dev/null +++ b/python/google/protobuf/pyext/repeated_scalar_container.cc @@ -0,0 +1,825 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: anuraag@google.com (Anuraag Agrawal) +// Author: tibell@google.com (Johan Tibell) + +#include + +#include +#ifndef _SHARED_PTR_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#if PY_MAJOR_VERSION >= 3 + #define PyInt_FromLong PyLong_FromLong + #if PY_VERSION_HEX < 0x03030000 + #error "Python 3.0 - 3.2 are not supported." + #else + #define PyString_AsString(ob) \ + (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AS_STRING(ob)) + #endif +#endif + +namespace google { +namespace protobuf { +namespace python { + +extern google::protobuf::DynamicMessageFactory* global_message_factory; + +namespace repeated_scalar_container { + +static int InternalAssignRepeatedField( + RepeatedScalarContainer* self, PyObject* list) { + self->message->GetReflection()->ClearField(self->message, + self->parent_field->descriptor); + for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) { + PyObject* value = PyList_GET_ITEM(list, i); + if (Append(self, value) == NULL) { + return -1; + } + } + return 0; +} + +static Py_ssize_t Len(RepeatedScalarContainer* self) { + google::protobuf::Message* message = self->message; + return message->GetReflection()->FieldSize(*message, + self->parent_field->descriptor); +} + +static int AssignItem(RepeatedScalarContainer* self, + Py_ssize_t index, + PyObject* arg) { + cmessage::AssureWritable(self->parent); + google::protobuf::Message* message = self->message; + const google::protobuf::FieldDescriptor* field_descriptor = + self->parent_field->descriptor; + if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) { + PyErr_SetString( + PyExc_KeyError, "Field does not belong to message!"); + return -1; + } + + const google::protobuf::Reflection* reflection = message->GetReflection(); + int field_size = reflection->FieldSize(*message, field_descriptor); + if (index < 0) { + index = field_size + index; + } + if (index < 0 || index >= field_size) { + PyErr_Format(PyExc_IndexError, + "list assignment index (%d) out of range", + static_cast(index)); + return -1; + } + + if (arg == NULL) { + ScopedPyObjectPtr py_index(PyLong_FromLong(index)); + return cmessage::InternalDeleteRepeatedField(message, field_descriptor, + py_index, NULL); + } + + if (PySequence_Check(arg) && !(PyBytes_Check(arg) || PyUnicode_Check(arg))) { + PyErr_SetString(PyExc_TypeError, "Value must be scalar"); + return -1; + } + + switch (field_descriptor->cpp_type()) { + case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { + GOOGLE_CHECK_GET_INT32(arg, value, -1); + reflection->SetRepeatedInt32(message, field_descriptor, index, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { + GOOGLE_CHECK_GET_INT64(arg, value, -1); + reflection->SetRepeatedInt64(message, field_descriptor, index, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { + GOOGLE_CHECK_GET_UINT32(arg, value, -1); + reflection->SetRepeatedUInt32(message, field_descriptor, index, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { + GOOGLE_CHECK_GET_UINT64(arg, value, -1); + reflection->SetRepeatedUInt64(message, field_descriptor, index, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { + GOOGLE_CHECK_GET_FLOAT(arg, value, -1); + reflection->SetRepeatedFloat(message, field_descriptor, index, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { + GOOGLE_CHECK_GET_DOUBLE(arg, value, -1); + reflection->SetRepeatedDouble(message, field_descriptor, index, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { + GOOGLE_CHECK_GET_BOOL(arg, value, -1); + reflection->SetRepeatedBool(message, field_descriptor, index, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { + if (!CheckAndSetString( + arg, message, field_descriptor, reflection, false, index)) { + return -1; + } + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { + GOOGLE_CHECK_GET_INT32(arg, value, -1); + const google::protobuf::EnumDescriptor* enum_descriptor = + field_descriptor->enum_type(); + const google::protobuf::EnumValueDescriptor* enum_value = + enum_descriptor->FindValueByNumber(value); + if (enum_value != NULL) { + reflection->SetRepeatedEnum(message, field_descriptor, index, + enum_value); + } else { + ScopedPyObjectPtr s(PyObject_Str(arg)); + if (s != NULL) { + PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", + PyString_AsString(s.get())); + } + return -1; + } + break; + } + default: + PyErr_Format( + PyExc_SystemError, "Adding value to a field of unknown type %d", + field_descriptor->cpp_type()); + return -1; + } + return 0; +} + +static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) { + google::protobuf::Message* message = self->message; + const google::protobuf::FieldDescriptor* field_descriptor = + self->parent_field->descriptor; + const google::protobuf::Reflection* reflection = message->GetReflection(); + + int field_size = reflection->FieldSize(*message, field_descriptor); + if (index < 0) { + index = field_size + index; + } + if (index < 0 || index >= field_size) { + PyErr_Format(PyExc_IndexError, + "list assignment index (%d) out of range", + static_cast(index)); + return NULL; + } + + PyObject* result = NULL; + switch (field_descriptor->cpp_type()) { + case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { + int32 value = reflection->GetRepeatedInt32( + *message, field_descriptor, index); + result = PyInt_FromLong(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { + int64 value = reflection->GetRepeatedInt64( + *message, field_descriptor, index); + result = PyLong_FromLongLong(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { + uint32 value = reflection->GetRepeatedUInt32( + *message, field_descriptor, index); + result = PyLong_FromLongLong(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { + uint64 value = reflection->GetRepeatedUInt64( + *message, field_descriptor, index); + result = PyLong_FromUnsignedLongLong(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { + float value = reflection->GetRepeatedFloat( + *message, field_descriptor, index); + result = PyFloat_FromDouble(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { + double value = reflection->GetRepeatedDouble( + *message, field_descriptor, index); + result = PyFloat_FromDouble(value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { + bool value = reflection->GetRepeatedBool( + *message, field_descriptor, index); + result = PyBool_FromLong(value ? 1 : 0); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { + const google::protobuf::EnumValueDescriptor* enum_value = + message->GetReflection()->GetRepeatedEnum( + *message, field_descriptor, index); + result = PyInt_FromLong(enum_value->number()); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { + string value = reflection->GetRepeatedString( + *message, field_descriptor, index); + result = ToStringObject(field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { + PyObject* py_cmsg = PyObject_CallObject(reinterpret_cast( + &CMessage_Type), NULL); + if (py_cmsg == NULL) { + return NULL; + } + CMessage* cmsg = reinterpret_cast(py_cmsg); + const google::protobuf::Message& msg = reflection->GetRepeatedMessage( + *message, field_descriptor, index); + cmsg->owner = self->owner; + cmsg->parent = self->parent; + cmsg->message = const_cast(&msg); + cmsg->read_only = false; + result = reinterpret_cast(py_cmsg); + break; + } + default: + PyErr_Format( + PyExc_SystemError, + "Getting value from a repeated field of unknown type %d", + field_descriptor->cpp_type()); + } + + return result; +} + +static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { + Py_ssize_t from; + Py_ssize_t to; + Py_ssize_t step; + Py_ssize_t length; + Py_ssize_t slicelength; + bool return_list = false; +#if PY_MAJOR_VERSION < 3 + if (PyInt_Check(slice)) { + from = to = PyInt_AsLong(slice); + } else // NOLINT +#endif + if (PyLong_Check(slice)) { + from = to = PyLong_AsLong(slice); + } else if (PySlice_Check(slice)) { + length = Len(self); +#if PY_MAJOR_VERSION >= 3 + if (PySlice_GetIndicesEx(slice, +#else + if (PySlice_GetIndicesEx(reinterpret_cast(slice), +#endif + length, &from, &to, &step, &slicelength) == -1) { + return NULL; + } + return_list = true; + } else { + PyErr_SetString(PyExc_TypeError, "list indices must be integers"); + return NULL; + } + + if (!return_list) { + return Item(self, from); + } + + PyObject* list = PyList_New(0); + if (list == NULL) { + return NULL; + } + if (from <= to) { + if (step < 0) { + return list; + } + for (Py_ssize_t index = from; index < to; index += step) { + if (index < 0 || index >= length) { + break; + } + ScopedPyObjectPtr s(Item(self, index)); + PyList_Append(list, s); + } + } else { + if (step > 0) { + return list; + } + for (Py_ssize_t index = from; index > to; index += step) { + if (index < 0 || index >= length) { + break; + } + ScopedPyObjectPtr s(Item(self, index)); + PyList_Append(list, s); + } + } + return list; +} + +PyObject* Append(RepeatedScalarContainer* self, PyObject* item) { + cmessage::AssureWritable(self->parent); + google::protobuf::Message* message = self->message; + const google::protobuf::FieldDescriptor* field_descriptor = + self->parent_field->descriptor; + + if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) { + PyErr_SetString( + PyExc_KeyError, "Field does not belong to message!"); + return NULL; + } + + const google::protobuf::Reflection* reflection = message->GetReflection(); + switch (field_descriptor->cpp_type()) { + case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { + GOOGLE_CHECK_GET_INT32(item, value, NULL); + reflection->AddInt32(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { + GOOGLE_CHECK_GET_INT64(item, value, NULL); + reflection->AddInt64(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { + GOOGLE_CHECK_GET_UINT32(item, value, NULL); + reflection->AddUInt32(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { + GOOGLE_CHECK_GET_UINT64(item, value, NULL); + reflection->AddUInt64(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { + GOOGLE_CHECK_GET_FLOAT(item, value, NULL); + reflection->AddFloat(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { + GOOGLE_CHECK_GET_DOUBLE(item, value, NULL); + reflection->AddDouble(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { + GOOGLE_CHECK_GET_BOOL(item, value, NULL); + reflection->AddBool(message, field_descriptor, value); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { + if (!CheckAndSetString( + item, message, field_descriptor, reflection, true, -1)) { + return NULL; + } + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { + GOOGLE_CHECK_GET_INT32(item, value, NULL); + const google::protobuf::EnumDescriptor* enum_descriptor = + field_descriptor->enum_type(); + const google::protobuf::EnumValueDescriptor* enum_value = + enum_descriptor->FindValueByNumber(value); + if (enum_value != NULL) { + reflection->AddEnum(message, field_descriptor, enum_value); + } else { + ScopedPyObjectPtr s(PyObject_Str(item)); + if (s != NULL) { + PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", + PyString_AsString(s.get())); + } + return NULL; + } + break; + } + default: + PyErr_Format( + PyExc_SystemError, "Adding value to a field of unknown type %d", + field_descriptor->cpp_type()); + return NULL; + } + + Py_RETURN_NONE; +} + +static int AssSubscript(RepeatedScalarContainer* self, + PyObject* slice, + PyObject* value) { + Py_ssize_t from; + Py_ssize_t to; + Py_ssize_t step; + Py_ssize_t length; + Py_ssize_t slicelength; + bool create_list = false; + + cmessage::AssureWritable(self->parent); + google::protobuf::Message* message = self->message; + const google::protobuf::FieldDescriptor* field_descriptor = + self->parent_field->descriptor; + +#if PY_MAJOR_VERSION < 3 + if (PyInt_Check(slice)) { + from = to = PyInt_AsLong(slice); + } else +#endif + if (PyLong_Check(slice)) { + from = to = PyLong_AsLong(slice); + } else if (PySlice_Check(slice)) { + const google::protobuf::Reflection* reflection = message->GetReflection(); + length = reflection->FieldSize(*message, field_descriptor); +#if PY_MAJOR_VERSION >= 3 + if (PySlice_GetIndicesEx(slice, +#else + if (PySlice_GetIndicesEx(reinterpret_cast(slice), +#endif + length, &from, &to, &step, &slicelength) == -1) { + return -1; + } + create_list = true; + } else { + PyErr_SetString(PyExc_TypeError, "list indices must be integers"); + return -1; + } + + if (value == NULL) { + return cmessage::InternalDeleteRepeatedField( + message, field_descriptor, slice, NULL); + } + + if (!create_list) { + return AssignItem(self, from, value); + } + + ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); + if (full_slice == NULL) { + return -1; + } + ScopedPyObjectPtr new_list(Subscript(self, full_slice)); + if (new_list == NULL) { + return -1; + } + if (PySequence_SetSlice(new_list, from, to, value) < 0) { + return -1; + } + + return InternalAssignRepeatedField(self, new_list); +} + +PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) { + cmessage::AssureWritable(self->parent); + if (PyObject_Not(value)) { + Py_RETURN_NONE; + } + ScopedPyObjectPtr iter(PyObject_GetIter(value)); + if (iter == NULL) { + PyErr_SetString(PyExc_TypeError, "Value must be iterable"); + return NULL; + } + ScopedPyObjectPtr next; + while ((next.reset(PyIter_Next(iter))) != NULL) { + if (Append(self, next) == NULL) { + return NULL; + } + } + if (PyErr_Occurred()) { + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject* Insert(RepeatedScalarContainer* self, PyObject* args) { + Py_ssize_t index; + PyObject* value; + if (!PyArg_ParseTuple(args, "lO", &index, &value)) { + return NULL; + } + ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); + ScopedPyObjectPtr new_list(Subscript(self, full_slice)); + if (PyList_Insert(new_list, index, value) < 0) { + return NULL; + } + int ret = InternalAssignRepeatedField(self, new_list); + if (ret < 0) { + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject* Remove(RepeatedScalarContainer* self, PyObject* value) { + Py_ssize_t match_index = -1; + for (Py_ssize_t i = 0; i < Len(self); ++i) { + ScopedPyObjectPtr elem(Item(self, i)); + if (PyObject_RichCompareBool(elem, value, Py_EQ)) { + match_index = i; + break; + } + } + if (match_index == -1) { + PyErr_SetString(PyExc_ValueError, "remove(x): x not in container"); + return NULL; + } + if (AssignItem(self, match_index, NULL) < 0) { + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject* RichCompare(RepeatedScalarContainer* self, + PyObject* other, + int opid) { + if (opid != Py_EQ && opid != Py_NE) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + // Copy the contents of this repeated scalar container, and other if it is + // also a repeated scalar container, into Python lists so we can delegate + // to the list's compare method. + + ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); + if (full_slice == NULL) { + return NULL; + } + + ScopedPyObjectPtr other_list_deleter; + if (PyObject_TypeCheck(other, &RepeatedScalarContainer_Type)) { + other_list_deleter.reset(Subscript( + reinterpret_cast(other), full_slice)); + other = other_list_deleter.get(); + } + + ScopedPyObjectPtr list(Subscript(self, full_slice)); + if (list == NULL) { + return NULL; + } + return PyObject_RichCompare(list, other, opid); +} + +PyObject* Reduce(RepeatedScalarContainer* unused_self) { + PyErr_Format( + PickleError_class, + "can't pickle repeated message fields, convert to list first"); + return NULL; +} + +static PyObject* Sort(RepeatedScalarContainer* self, + PyObject* args, + PyObject* kwds) { + // Support the old sort_function argument for backwards + // compatibility. + if (kwds != NULL) { + PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function"); + if (sort_func != NULL) { + // Must set before deleting as sort_func is a borrowed reference + // and kwds might be the only thing keeping it alive. + if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1) + return NULL; + if (PyDict_DelItemString(kwds, "sort_function") == -1) + return NULL; + } + } + + ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); + if (full_slice == NULL) { + return NULL; + } + ScopedPyObjectPtr list(Subscript(self, full_slice)); + if (list == NULL) { + return NULL; + } + ScopedPyObjectPtr m(PyObject_GetAttrString(list, "sort")); + if (m == NULL) { + return NULL; + } + ScopedPyObjectPtr res(PyObject_Call(m, args, kwds)); + if (res == NULL) { + return NULL; + } + int ret = InternalAssignRepeatedField(self, list); + if (ret < 0) { + return NULL; + } + Py_RETURN_NONE; +} + +static int Init(RepeatedScalarContainer* self, + PyObject* args, + PyObject* kwargs) { + PyObject* py_parent; + PyObject* py_parent_field; + if (!PyArg_UnpackTuple(args, "__init__()", 2, 2, &py_parent, + &py_parent_field)) { + return -1; + } + + if (!PyObject_TypeCheck(py_parent, &CMessage_Type)) { + PyErr_Format(PyExc_TypeError, + "expect %s, but got %s", + CMessage_Type.tp_name, + Py_TYPE(py_parent)->tp_name); + return -1; + } + + if (!PyObject_TypeCheck(py_parent_field, &CFieldDescriptor_Type)) { + PyErr_Format(PyExc_TypeError, + "expect %s, but got %s", + CFieldDescriptor_Type.tp_name, + Py_TYPE(py_parent_field)->tp_name); + return -1; + } + + CMessage* cmessage = reinterpret_cast(py_parent); + CFieldDescriptor* cdescriptor = reinterpret_cast( + py_parent_field); + + if (!FIELD_BELONGS_TO_MESSAGE(cdescriptor->descriptor, cmessage->message)) { + PyErr_SetString( + PyExc_KeyError, "Field does not belong to message!"); + return -1; + } + + self->message = cmessage->message; + self->parent = cmessage; + self->parent_field = cdescriptor; + self->owner = cmessage->owner; + return 0; +} + +// Initializes the underlying Message object of "to" so it becomes a new parent +// repeated scalar, and copies all the values from "from" to it. A child scalar +// container can be released by passing it as both from and to (e.g. making it +// the recipient of the new parent message and copying the values from itself). +static int InitializeAndCopyToParentContainer( + RepeatedScalarContainer* from, + RepeatedScalarContainer* to) { + ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); + if (full_slice == NULL) { + return -1; + } + ScopedPyObjectPtr values(Subscript(from, full_slice)); + if (values == NULL) { + return -1; + } + google::protobuf::Message* new_message = global_message_factory->GetPrototype( + from->message->GetDescriptor())->New(); + to->parent = NULL; + // TODO(anuraag): Document why it's OK to hang on to parent_field, + // even though it's a weak reference. It ought to be enough to + // hold on to the FieldDescriptor only. + to->parent_field = from->parent_field; + to->message = new_message; + to->owner.reset(new_message); + if (InternalAssignRepeatedField(to, values) < 0) { + return -1; + } + return 0; +} + +int Release(RepeatedScalarContainer* self) { + return InitializeAndCopyToParentContainer(self, self); +} + +PyObject* DeepCopy(RepeatedScalarContainer* self, PyObject* arg) { + ScopedPyObjectPtr init_args( + PyTuple_Pack(2, self->parent, self->parent_field)); + PyObject* clone = PyObject_CallObject( + reinterpret_cast(&RepeatedScalarContainer_Type), init_args); + if (clone == NULL) { + return NULL; + } + if (!PyObject_TypeCheck(clone, &RepeatedScalarContainer_Type)) { + Py_DECREF(clone); + return NULL; + } + if (InitializeAndCopyToParentContainer( + self, reinterpret_cast(clone)) < 0) { + Py_DECREF(clone); + return NULL; + } + return clone; +} + +static void Dealloc(RepeatedScalarContainer* self) { + self->owner.reset(); + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +void SetOwner(RepeatedScalarContainer* self, + const shared_ptr& new_owner) { + self->owner = new_owner; +} + +static PySequenceMethods SqMethods = { + (lenfunc)Len, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + (ssizeargfunc)Item, /* sq_item */ + 0, /* sq_slice */ + (ssizeobjargproc)AssignItem /* sq_ass_item */ +}; + +static PyMappingMethods MpMethods = { + (lenfunc)Len, /* mp_length */ + (binaryfunc)Subscript, /* mp_subscript */ + (objobjargproc)AssSubscript, /* mp_ass_subscript */ +}; + +static PyMethodDef Methods[] = { + { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, + "Makes a deep copy of the class." }, + { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, + "Outputs picklable representation of the repeated field." }, + { "append", (PyCFunction)Append, METH_O, + "Appends an object to the repeated container." }, + { "extend", (PyCFunction)Extend, METH_O, + "Appends objects to the repeated container." }, + { "insert", (PyCFunction)Insert, METH_VARARGS, + "Appends objects to the repeated container." }, + { "remove", (PyCFunction)Remove, METH_O, + "Removes an object from the repeated container." }, + { "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS, + "Sorts the repeated container."}, + { NULL, NULL } +}; + +} // namespace repeated_scalar_container + +PyTypeObject RepeatedScalarContainer_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "google.protobuf.internal." + "cpp._message.RepeatedScalarContainer", // tp_name + sizeof(RepeatedScalarContainer), // tp_basicsize + 0, // tp_itemsize + (destructor)repeated_scalar_container::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &repeated_scalar_container::SqMethods, // tp_as_sequence + &repeated_scalar_container::MpMethods, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "A Repeated scalar container", // tp_doc + 0, // tp_traverse + 0, // tp_clear + (richcmpfunc)repeated_scalar_container::RichCompare, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + repeated_scalar_container::Methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + (initproc)repeated_scalar_container::Init, // tp_init +}; + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/pyext/repeated_scalar_container.h b/python/google/protobuf/pyext/repeated_scalar_container.h new file mode 100644 index 0000000..8a30138 --- /dev/null +++ b/python/google/protobuf/pyext/repeated_scalar_container.h @@ -0,0 +1,112 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: anuraag@google.com (Anuraag Agrawal) +// Author: tibell@google.com (Johan Tibell) + +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_SCALAR_CONTAINER_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_SCALAR_CONTAINER_H__ + +#include + +#include +#ifndef _SHARED_PTR_H +#include +#endif + + +namespace google { +namespace protobuf { + +class Message; + +using internal::shared_ptr; + +namespace python { + +struct CFieldDescriptor; +struct CMessage; + +typedef struct RepeatedScalarContainer { + PyObject_HEAD; + + // This is the top-level C++ Message object that owns the whole + // proto tree. Every Python RepeatedScalarContainer holds a + // reference to it in order to keep it alive as long as there's a + // Python object that references any part of the tree. + shared_ptr owner; + + // Pointer to the C++ Message that contains this container. The + // RepeatedScalarContainer does not own this pointer. + Message* message; + + // Weak reference to a parent CMessage object (i.e. may be NULL.) + // + // Used to make sure all ancestors are also mutable when first + // modifying the container. + CMessage* parent; + + // Weak reference to the parent's descriptor that describes this + // field. Used together with the parent's message when making a + // default message instance mutable. + CFieldDescriptor* parent_field; +} RepeatedScalarContainer; + +extern PyTypeObject RepeatedScalarContainer_Type; + +namespace repeated_scalar_container { + +// Appends the scalar 'item' to the end of the container 'self'. +// +// Returns None if successful; returns NULL and sets an exception if +// unsuccessful. +PyObject* Append(RepeatedScalarContainer* self, PyObject* item); + +// Releases the messages in the container to a new message. +// +// Returns 0 on success, -1 on failure. +int Release(RepeatedScalarContainer* self); + +// Appends all the elements in the input iterator to the container. +// +// Returns None if successful; returns NULL and sets an exception if +// unsuccessful. +PyObject* Extend(RepeatedScalarContainer* self, PyObject* value); + +// Set the owner field of self and any children of self. +void SetOwner(RepeatedScalarContainer* self, + const shared_ptr& new_owner); + +} // namespace repeated_scalar_container +} // namespace python +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_SCALAR_CONTAINER_H__ diff --git a/python/google/protobuf/pyext/scoped_pyobject_ptr.h b/python/google/protobuf/pyext/scoped_pyobject_ptr.h new file mode 100644 index 0000000..1b27a89 --- /dev/null +++ b/python/google/protobuf/pyext/scoped_pyobject_ptr.h @@ -0,0 +1,95 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: tibell@google.com (Johan Tibell) + +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__ + +#include + +namespace google { +class ScopedPyObjectPtr { + public: + // Constructor. Defaults to intializing with NULL. + // There is no way to create an uninitialized ScopedPyObjectPtr. + explicit ScopedPyObjectPtr(PyObject* p = NULL) : ptr_(p) { } + + // Destructor. If there is a PyObject object, delete it. + ~ScopedPyObjectPtr() { + Py_XDECREF(ptr_); + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + PyObject* reset(PyObject* p = NULL) { + if (p != ptr_) { + Py_XDECREF(ptr_); + ptr_ = p; + } + return ptr_; + } + + // Releases ownership of the object. + PyObject* release() { + PyObject* p = ptr_; + ptr_ = NULL; + return p; + } + + operator PyObject*() { return ptr_; } + + PyObject* operator->() const { + assert(ptr_ != NULL); + return ptr_; + } + + PyObject* get() const { return ptr_; } + + Py_ssize_t refcnt() const { return Py_REFCNT(ptr_); } + + void inc() const { Py_INCREF(ptr_); } + + // Comparison operators. + // These return whether a ScopedPyObjectPtr and a raw pointer + // refer to the same object, not just to two different but equal + // objects. + bool operator==(const PyObject* p) const { return ptr_ == p; } + bool operator!=(const PyObject* p) const { return ptr_ != p; } + + private: + PyObject* ptr_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ScopedPyObjectPtr); +}; + +} // namespace google +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__ diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py index 5b23803..7aac623 100755 --- a/python/google/protobuf/reflection.py +++ b/python/google/protobuf/reflection.py @@ -29,9 +29,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # This code is meant to work on Python 2.4 and above only. -# -# TODO(robinson): Helpers for verbose, common checks like seeing if a -# descriptor's cpp_type is CPPTYPE_MESSAGE. """Contains a metaclass and helper functions used to create protocol message classes from Descriptor objects at runtime. @@ -50,27 +47,29 @@ this file*. __author__ = 'robinson@google.com (Will Robinson)' -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO -import struct -import weakref -# We use "as" to avoid name collisions with variables. -from google.protobuf.internal import containers -from google.protobuf.internal import decoder -from google.protobuf.internal import encoder -from google.protobuf.internal import message_listener as message_listener_mod -from google.protobuf.internal import type_checkers -from google.protobuf.internal import wire_format +from google.protobuf.internal import api_implementation from google.protobuf import descriptor as descriptor_mod -from google.protobuf import message as message_mod -from google.protobuf import text_format +from google.protobuf import message _FieldDescriptor = descriptor_mod.FieldDescriptor +if api_implementation.Type() == 'cpp': + if api_implementation.Version() == 2: + from google.protobuf.pyext import cpp_message + _NewMessage = cpp_message.NewMessage + _InitMessage = cpp_message.InitMessage + else: + from google.protobuf.internal import cpp_message + _NewMessage = cpp_message.NewMessage + _InitMessage = cpp_message.InitMessage +else: + from google.protobuf.internal import python_message + _NewMessage = python_message.NewMessage + _InitMessage = python_message.InitMessage + + class GeneratedProtocolMessageType(type): """Metaclass for protocol message classes created at runtime from Descriptors. @@ -92,6 +91,10 @@ class GeneratedProtocolMessageType(type): myproto_instance = MyProtoClass() myproto.foo_field = 23 ... + + The above example will not work for nested types. If you wish to include them, + use reflection.MakeClass() instead of manually instantiating the class in + order to create the appropriate class structure. """ # Must be consistent with the protocol-compiler code in @@ -120,10 +123,12 @@ class GeneratedProtocolMessageType(type): Newly-allocated class. """ descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY] - _AddSlots(descriptor, dictionary) - _AddClassAttributesForNestedExtensions(descriptor, dictionary) + bases = _NewMessage(bases, descriptor, dictionary) superclass = super(GeneratedProtocolMessageType, cls) - return superclass.__new__(cls, name, bases, dictionary) + + new_class = superclass.__new__(cls, name, bases, dictionary) + setattr(descriptor, '_concrete_class', new_class) + return new_class def __init__(cls, name, bases, dictionary): """Here we perform the majority of our work on the class. @@ -143,1006 +148,58 @@ class GeneratedProtocolMessageType(type): type. """ descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY] - - cls._decoders_by_tag = {} - cls._extensions_by_name = {} - cls._extensions_by_number = {} - if (descriptor.has_options and - descriptor.GetOptions().message_set_wire_format): - cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = ( - decoder.MessageSetItemDecoder(cls._extensions_by_number)) - - # We act as a "friend" class of the descriptor, setting - # its _concrete_class attribute the first time we use a - # given descriptor to initialize a concrete protocol message - # class. We also attach stuff to each FieldDescriptor for quick - # lookup later on. - concrete_class_attr_name = '_concrete_class' - if not hasattr(descriptor, concrete_class_attr_name): - setattr(descriptor, concrete_class_attr_name, cls) - for field in descriptor.fields: - _AttachFieldHelpers(cls, field) - - _AddEnumValues(descriptor, cls) - _AddInitMethod(descriptor, cls) - _AddPropertiesForFields(descriptor, cls) - _AddPropertiesForExtensions(descriptor, cls) - _AddStaticMethods(cls) - _AddMessageMethods(descriptor, cls) - _AddPrivateHelperMethods(cls) + _InitMessage(descriptor, cls) superclass = super(GeneratedProtocolMessageType, cls) superclass.__init__(name, bases, dictionary) -# Stateless helpers for GeneratedProtocolMessageType below. -# Outside clients should not access these directly. -# -# I opted not to make any of these methods on the metaclass, to make it more -# clear that I'm not really using any state there and to keep clients from -# thinking that they have direct access to these construction helpers. - - -def _PropertyName(proto_field_name): - """Returns the name of the public property attribute which - clients can use to get and (in some cases) set the value - of a protocol message field. - - Args: - proto_field_name: The protocol message field name, exactly - as it appears (or would appear) in a .proto file. - """ - # TODO(robinson): Escape Python keywords (e.g., yield), and test this support. - # nnorwitz makes my day by writing: - # """ - # FYI. See the keyword module in the stdlib. This could be as simple as: - # - # if keyword.iskeyword(proto_field_name): - # return proto_field_name + "_" - # return proto_field_name - # """ - # Kenton says: The above is a BAD IDEA. People rely on being able to use - # getattr() and setattr() to reflectively manipulate field values. If we - # rename the properties, then every such user has to also make sure to apply - # the same transformation. Note that currently if you name a field "yield", - # you can still access it just fine using getattr/setattr -- it's not even - # that cumbersome to do so. - # TODO(kenton): Remove this method entirely if/when everyone agrees with my - # position. - return proto_field_name - - -def _VerifyExtensionHandle(message, extension_handle): - """Verify that the given extension handle is valid.""" - - if not isinstance(extension_handle, _FieldDescriptor): - raise KeyError('HasExtension() expects an extension handle, got: %s' % - extension_handle) - - if not extension_handle.is_extension: - raise KeyError('"%s" is not an extension.' % extension_handle.full_name) - - if extension_handle.containing_type is not message.DESCRIPTOR: - raise KeyError('Extension "%s" extends message type "%s", but this ' - 'message is of type "%s".' % - (extension_handle.full_name, - extension_handle.containing_type.full_name, - message.DESCRIPTOR.full_name)) - - -def _AddSlots(message_descriptor, dictionary): - """Adds a __slots__ entry to dictionary, containing the names of all valid - attributes for this message type. - - Args: - message_descriptor: A Descriptor instance describing this message type. - dictionary: Class dictionary to which we'll add a '__slots__' entry. - """ - dictionary['__slots__'] = ['_cached_byte_size', - '_cached_byte_size_dirty', - '_fields', - '_is_present_in_parent', - '_listener', - '_listener_for_children', - '__weakref__'] - - -def _IsMessageSetExtension(field): - return (field.is_extension and - field.containing_type.has_options and - field.containing_type.GetOptions().message_set_wire_format and - field.type == _FieldDescriptor.TYPE_MESSAGE and - field.message_type == field.extension_scope and - field.label == _FieldDescriptor.LABEL_OPTIONAL) - - -def _AttachFieldHelpers(cls, field_descriptor): - is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED) - is_packed = (field_descriptor.has_options and - field_descriptor.GetOptions().packed) - - if _IsMessageSetExtension(field_descriptor): - field_encoder = encoder.MessageSetItemEncoder(field_descriptor.number) - sizer = encoder.MessageSetItemSizer(field_descriptor.number) - else: - field_encoder = type_checkers.TYPE_TO_ENCODER[field_descriptor.type]( - field_descriptor.number, is_repeated, is_packed) - sizer = type_checkers.TYPE_TO_SIZER[field_descriptor.type]( - field_descriptor.number, is_repeated, is_packed) - - field_descriptor._encoder = field_encoder - field_descriptor._sizer = sizer - field_descriptor._default_constructor = _DefaultValueConstructorForField( - field_descriptor) - - def AddDecoder(wiretype, is_packed): - tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype) - cls._decoders_by_tag[tag_bytes] = ( - type_checkers.TYPE_TO_DECODER[field_descriptor.type]( - field_descriptor.number, is_repeated, is_packed, - field_descriptor, field_descriptor._default_constructor)) - - AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type], - False) - - if is_repeated and wire_format.IsTypePackable(field_descriptor.type): - # To support wire compatibility of adding packed = true, add a decoder for - # packed values regardless of the field's options. - AddDecoder(wire_format.WIRETYPE_LENGTH_DELIMITED, True) - - -def _AddClassAttributesForNestedExtensions(descriptor, dictionary): - extension_dict = descriptor.extensions_by_name - for extension_name, extension_field in extension_dict.iteritems(): - assert extension_name not in dictionary - dictionary[extension_name] = extension_field - - -def _AddEnumValues(descriptor, cls): - """Sets class-level attributes for all enum fields defined in this message. - - Args: - descriptor: Descriptor object for this message type. - cls: Class we're constructing for this message type. - """ - for enum_type in descriptor.enum_types: - for enum_value in enum_type.values: - setattr(cls, enum_value.name, enum_value.number) - - -def _DefaultValueConstructorForField(field): - """Returns a function which returns a default value for a field. +def ParseMessage(descriptor, byte_str): + """Generate a new Message instance from this Descriptor and a byte string. Args: - field: FieldDescriptor object for this field. + descriptor: Protobuf Descriptor object + byte_str: Serialized protocol buffer byte string - The returned function has one argument: - message: Message instance containing this field, or a weakref proxy - of same. - - That function in turn returns a default value for this field. The default - value may refer back to |message| via a weak reference. - """ - - if field.label == _FieldDescriptor.LABEL_REPEATED: - if field.default_value != []: - raise ValueError('Repeated field default value not empty list: %s' % ( - field.default_value)) - if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - # We can't look at _concrete_class yet since it might not have - # been set. (Depends on order in which we initialize the classes). - message_type = field.message_type - def MakeRepeatedMessageDefault(message): - return containers.RepeatedCompositeFieldContainer( - message._listener_for_children, field.message_type) - return MakeRepeatedMessageDefault - else: - type_checker = type_checkers.GetTypeChecker(field.cpp_type, field.type) - def MakeRepeatedScalarDefault(message): - return containers.RepeatedScalarFieldContainer( - message._listener_for_children, type_checker) - return MakeRepeatedScalarDefault - - if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - # _concrete_class may not yet be initialized. - message_type = field.message_type - def MakeSubMessageDefault(message): - result = message_type._concrete_class() - result._SetListener(message._listener_for_children) - return result - return MakeSubMessageDefault - - def MakeScalarDefault(message): - return field.default_value - return MakeScalarDefault - - -def _AddInitMethod(message_descriptor, cls): - """Adds an __init__ method to cls.""" - fields = message_descriptor.fields - def init(self, **kwargs): - self._cached_byte_size = 0 - self._cached_byte_size_dirty = False - self._fields = {} - self._is_present_in_parent = False - self._listener = message_listener_mod.NullMessageListener() - self._listener_for_children = _Listener(self) - for field_name, field_value in kwargs.iteritems(): - field = _GetFieldByName(message_descriptor, field_name) - if field is None: - raise TypeError("%s() got an unexpected keyword argument '%s'" % - (message_descriptor.name, field_name)) - if field.label == _FieldDescriptor.LABEL_REPEATED: - copy = field._default_constructor(self) - if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite - for val in field_value: - copy.add().MergeFrom(val) - else: # Scalar - copy.extend(field_value) - self._fields[field] = copy - elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - copy = field._default_constructor(self) - copy.MergeFrom(field_value) - self._fields[field] = copy - else: - self._fields[field] = field_value - - init.__module__ = None - init.__doc__ = None - cls.__init__ = init - - -def _GetFieldByName(message_descriptor, field_name): - """Returns a field descriptor by field name. - - Args: - message_descriptor: A Descriptor describing all fields in message. - field_name: The name of the field to retrieve. Returns: - The field descriptor associated with the field name. - """ - try: - return message_descriptor.fields_by_name[field_name] - except KeyError: - raise ValueError('Protocol message has no "%s" field.' % field_name) - - -def _AddPropertiesForFields(descriptor, cls): - """Adds properties for all fields in this protocol message type.""" - for field in descriptor.fields: - _AddPropertiesForField(field, cls) - - if descriptor.is_extendable: - # _ExtensionDict is just an adaptor with no state so we allocate a new one - # every time it is accessed. - cls.Extensions = property(lambda self: _ExtensionDict(self)) - - -def _AddPropertiesForField(field, cls): - """Adds a public property for a protocol message field. - Clients can use this property to get and (in the case - of non-repeated scalar fields) directly set the value - of a protocol message field. - - Args: - field: A FieldDescriptor for this field. - cls: The class we're constructing. - """ - # Catch it if we add other types that we should - # handle specially here. - assert _FieldDescriptor.MAX_CPPTYPE == 10 - - constant_name = field.name.upper() + "_FIELD_NUMBER" - setattr(cls, constant_name, field.number) - - if field.label == _FieldDescriptor.LABEL_REPEATED: - _AddPropertiesForRepeatedField(field, cls) - elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - _AddPropertiesForNonRepeatedCompositeField(field, cls) - else: - _AddPropertiesForNonRepeatedScalarField(field, cls) - - -def _AddPropertiesForRepeatedField(field, cls): - """Adds a public property for a "repeated" protocol message field. Clients - can use this property to get the value of the field, which will be either a - _RepeatedScalarFieldContainer or _RepeatedCompositeFieldContainer (see - below). - - Note that when clients add values to these containers, we perform - type-checking in the case of repeated scalar fields, and we also set any - necessary "has" bits as a side-effect. - - Args: - field: A FieldDescriptor for this field. - cls: The class we're constructing. - """ - proto_field_name = field.name - property_name = _PropertyName(proto_field_name) - - def getter(self): - field_value = self._fields.get(field) - if field_value is None: - # Construct a new object to represent this field. - field_value = field._default_constructor(self) - - # Atomically check if another thread has preempted us and, if not, swap - # in the new object we just created. If someone has preempted us, we - # take that object and discard ours. - # WARNING: We are relying on setdefault() being atomic. This is true - # in CPython but we haven't investigated others. This warning appears - # in several other locations in this file. - field_value = self._fields.setdefault(field, field_value) - return field_value - getter.__module__ = None - getter.__doc__ = 'Getter for %s.' % proto_field_name - - # We define a setter just so we can throw an exception with a more - # helpful error message. - def setter(self, new_value): - raise AttributeError('Assignment not allowed to repeated field ' - '"%s" in protocol message object.' % proto_field_name) - - doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name - setattr(cls, property_name, property(getter, setter, doc=doc)) - - -def _AddPropertiesForNonRepeatedScalarField(field, cls): - """Adds a public property for a nonrepeated, scalar protocol message field. - Clients can use this property to get and directly set the value of the field. - Note that when the client sets the value of a field by using this property, - all necessary "has" bits are set as a side-effect, and we also perform - type-checking. - - Args: - field: A FieldDescriptor for this field. - cls: The class we're constructing. - """ - proto_field_name = field.name - property_name = _PropertyName(proto_field_name) - type_checker = type_checkers.GetTypeChecker(field.cpp_type, field.type) - default_value = field.default_value - - def getter(self): - return self._fields.get(field, default_value) - getter.__module__ = None - getter.__doc__ = 'Getter for %s.' % proto_field_name - def setter(self, new_value): - type_checker.CheckValue(new_value) - self._fields[field] = new_value - # Check _cached_byte_size_dirty inline to improve performance, since scalar - # setters are called frequently. - if not self._cached_byte_size_dirty: - self._Modified() - setter.__module__ = None - setter.__doc__ = 'Setter for %s.' % proto_field_name - - # Add a property to encapsulate the getter/setter. - doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name - setattr(cls, property_name, property(getter, setter, doc=doc)) - - -def _AddPropertiesForNonRepeatedCompositeField(field, cls): - """Adds a public property for a nonrepeated, composite protocol message field. - A composite field is a "group" or "message" field. - - Clients can use this property to get the value of the field, but cannot - assign to the property directly. - - Args: - field: A FieldDescriptor for this field. - cls: The class we're constructing. + Newly created protobuf Message object. """ - # TODO(robinson): Remove duplication with similar method - # for non-repeated scalars. - proto_field_name = field.name - property_name = _PropertyName(proto_field_name) - message_type = field.message_type - - def getter(self): - field_value = self._fields.get(field) - if field_value is None: - # Construct a new object to represent this field. - field_value = message_type._concrete_class() - field_value._SetListener(self._listener_for_children) - - # Atomically check if another thread has preempted us and, if not, swap - # in the new object we just created. If someone has preempted us, we - # take that object and discard ours. - # WARNING: We are relying on setdefault() being atomic. This is true - # in CPython but we haven't investigated others. This warning appears - # in several other locations in this file. - field_value = self._fields.setdefault(field, field_value) - return field_value - getter.__module__ = None - getter.__doc__ = 'Getter for %s.' % proto_field_name - - # We define a setter just so we can throw an exception with a more - # helpful error message. - def setter(self, new_value): - raise AttributeError('Assignment not allowed to composite field ' - '"%s" in protocol message object.' % proto_field_name) - - # Add a property to encapsulate the getter. - doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name - setattr(cls, property_name, property(getter, setter, doc=doc)) - - -def _AddPropertiesForExtensions(descriptor, cls): - """Adds properties for all fields in this protocol message type.""" - extension_dict = descriptor.extensions_by_name - for extension_name, extension_field in extension_dict.iteritems(): - constant_name = extension_name.upper() + "_FIELD_NUMBER" - setattr(cls, constant_name, extension_field.number) - - -def _AddStaticMethods(cls): - # TODO(robinson): This probably needs to be thread-safe(?) - def RegisterExtension(extension_handle): - extension_handle.containing_type = cls.DESCRIPTOR - _AttachFieldHelpers(cls, extension_handle) - - # Try to insert our extension, failing if an extension with the same number - # already exists. - actual_handle = cls._extensions_by_number.setdefault( - extension_handle.number, extension_handle) - if actual_handle is not extension_handle: - raise AssertionError( - 'Extensions "%s" and "%s" both try to extend message type "%s" with ' - 'field number %d.' % - (extension_handle.full_name, actual_handle.full_name, - cls.DESCRIPTOR.full_name, extension_handle.number)) - - cls._extensions_by_name[extension_handle.full_name] = extension_handle - - handle = extension_handle # avoid line wrapping - if _IsMessageSetExtension(handle): - # MessageSet extension. Also register under type name. - cls._extensions_by_name[ - extension_handle.message_type.full_name] = extension_handle - - cls.RegisterExtension = staticmethod(RegisterExtension) - - def FromString(s): - message = cls() - message.MergeFromString(s) - return message - cls.FromString = staticmethod(FromString) - - -def _IsPresent(item): - """Given a (FieldDescriptor, value) tuple from _fields, return true if the - value should be included in the list returned by ListFields().""" - - if item[0].label == _FieldDescriptor.LABEL_REPEATED: - return bool(item[1]) - elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - return item[1]._is_present_in_parent - else: - return True - - -def _AddListFieldsMethod(message_descriptor, cls): - """Helper for _AddMessageMethods().""" - - def ListFields(self): - all_fields = [item for item in self._fields.iteritems() if _IsPresent(item)] - all_fields.sort(key = lambda item: item[0].number) - return all_fields - - cls.ListFields = ListFields - - -def _AddHasFieldMethod(message_descriptor, cls): - """Helper for _AddMessageMethods().""" - - singular_fields = {} - for field in message_descriptor.fields: - if field.label != _FieldDescriptor.LABEL_REPEATED: - singular_fields[field.name] = field - - def HasField(self, field_name): - try: - field = singular_fields[field_name] - except KeyError: - raise ValueError( - 'Protocol message has no singular "%s" field.' % field_name) - - if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - value = self._fields.get(field) - return value is not None and value._is_present_in_parent - else: - return field in self._fields - cls.HasField = HasField + result_class = MakeClass(descriptor) + new_msg = result_class() + new_msg.ParseFromString(byte_str) + return new_msg -def _AddClearFieldMethod(message_descriptor, cls): - """Helper for _AddMessageMethods().""" - def ClearField(self, field_name): - try: - field = message_descriptor.fields_by_name[field_name] - except KeyError: - raise ValueError('Protocol message has no "%s" field.' % field_name) +def MakeClass(descriptor): + """Construct a class object for a protobuf described by descriptor. - if field in self._fields: - # Note: If the field is a sub-message, its listener will still point - # at us. That's fine, because the worst than can happen is that it - # will call _Modified() and invalidate our byte size. Big deal. - del self._fields[field] + Composite descriptors are handled by defining the new class as a member of the + parent class, recursing as deep as necessary. + This is the dynamic equivalent to: - # Always call _Modified() -- even if nothing was changed, this is - # a mutating method, and thus calling it should cause the field to become - # present in the parent message. - self._Modified() - - cls.ClearField = ClearField - - -def _AddClearExtensionMethod(cls): - """Helper for _AddMessageMethods().""" - def ClearExtension(self, extension_handle): - _VerifyExtensionHandle(self, extension_handle) - - # Similar to ClearField(), above. - if extension_handle in self._fields: - del self._fields[extension_handle] - self._Modified() - cls.ClearExtension = ClearExtension - - -def _AddClearMethod(message_descriptor, cls): - """Helper for _AddMessageMethods().""" - def Clear(self): - # Clear fields. - self._fields = {} - self._Modified() - cls.Clear = Clear - - -def _AddHasExtensionMethod(cls): - """Helper for _AddMessageMethods().""" - def HasExtension(self, extension_handle): - _VerifyExtensionHandle(self, extension_handle) - if extension_handle.label == _FieldDescriptor.LABEL_REPEATED: - raise KeyError('"%s" is repeated.' % extension_handle.full_name) - - if extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - value = self._fields.get(extension_handle) - return value is not None and value._is_present_in_parent - else: - return extension_handle in self._fields - cls.HasExtension = HasExtension - - -def _AddEqualsMethod(message_descriptor, cls): - """Helper for _AddMessageMethods().""" - def __eq__(self, other): - if (not isinstance(other, message_mod.Message) or - other.DESCRIPTOR != self.DESCRIPTOR): - return False - - if self is other: - return True - - return self.ListFields() == other.ListFields() - - cls.__eq__ = __eq__ - - -def _AddStrMethod(message_descriptor, cls): - """Helper for _AddMessageMethods().""" - def __str__(self): - return text_format.MessageToString(self) - cls.__str__ = __str__ - - -def _AddSetListenerMethod(cls): - """Helper for _AddMessageMethods().""" - def SetListener(self, listener): - if listener is None: - self._listener = message_listener_mod.NullMessageListener() - else: - self._listener = listener - cls._SetListener = SetListener - - -def _BytesForNonRepeatedElement(value, field_number, field_type): - """Returns the number of bytes needed to serialize a non-repeated element. - The returned byte count includes space for tag information and any - other additional space associated with serializing value. + class Parent(message.Message): + __metaclass__ = GeneratedProtocolMessageType + DESCRIPTOR = descriptor + class Child(message.Message): + __metaclass__ = GeneratedProtocolMessageType + DESCRIPTOR = descriptor.nested_types[0] + + Sample usage: + file_descriptor = descriptor_pb2.FileDescriptorProto() + file_descriptor.ParseFromString(proto2_string) + msg_descriptor = descriptor.MakeDescriptor(file_descriptor.message_type[0]) + msg_class = reflection.MakeClass(msg_descriptor) + msg = msg_class() Args: - value: Value we're serializing. - field_number: Field number of this value. (Since the field number - is stored as part of a varint-encoded tag, this has an impact - on the total bytes required to serialize the value). - field_type: The type of the field. One of the TYPE_* constants - within FieldDescriptor. - """ - try: - fn = type_checkers.TYPE_TO_BYTE_SIZE_FN[field_type] - return fn(field_number, value) - except KeyError: - raise message_mod.EncodeError('Unrecognized field type: %d' % field_type) - - -def _AddByteSizeMethod(message_descriptor, cls): - """Helper for _AddMessageMethods().""" - - def ByteSize(self): - if not self._cached_byte_size_dirty: - return self._cached_byte_size - - size = 0 - for field_descriptor, field_value in self.ListFields(): - size += field_descriptor._sizer(field_value) - - self._cached_byte_size = size - self._cached_byte_size_dirty = False - self._listener_for_children.dirty = False - return size - - cls.ByteSize = ByteSize - - -def _AddSerializeToStringMethod(message_descriptor, cls): - """Helper for _AddMessageMethods().""" - - def SerializeToString(self): - # Check if the message has all of its required fields set. - errors = [] - if not self.IsInitialized(): - raise message_mod.EncodeError( - 'Message is missing required fields: ' + - ','.join(self.FindInitializationErrors())) - return self.SerializePartialToString() - cls.SerializeToString = SerializeToString - - -def _AddSerializePartialToStringMethod(message_descriptor, cls): - """Helper for _AddMessageMethods().""" - - def SerializePartialToString(self): - out = StringIO() - self._InternalSerialize(out.write) - return out.getvalue() - cls.SerializePartialToString = SerializePartialToString - - def InternalSerialize(self, write_bytes): - for field_descriptor, field_value in self.ListFields(): - field_descriptor._encoder(write_bytes, field_value) - cls._InternalSerialize = InternalSerialize - - -def _AddMergeFromStringMethod(message_descriptor, cls): - """Helper for _AddMessageMethods().""" - def MergeFromString(self, serialized): - length = len(serialized) - try: - if self._InternalParse(serialized, 0, length) != length: - # The only reason _InternalParse would return early is if it - # encountered an end-group tag. - raise message_mod.DecodeError('Unexpected end-group tag.') - except IndexError: - raise message_mod.DecodeError('Truncated message.') - except struct.error, e: - raise message_mod.DecodeError(e) - return length # Return this for legacy reasons. - cls.MergeFromString = MergeFromString - - local_ReadTag = decoder.ReadTag - local_SkipField = decoder.SkipField - decoders_by_tag = cls._decoders_by_tag - - def InternalParse(self, buffer, pos, end): - self._Modified() - field_dict = self._fields - while pos != end: - (tag_bytes, new_pos) = local_ReadTag(buffer, pos) - field_decoder = decoders_by_tag.get(tag_bytes) - if field_decoder is None: - new_pos = local_SkipField(buffer, new_pos, end, tag_bytes) - if new_pos == -1: - return pos - pos = new_pos - else: - pos = field_decoder(buffer, new_pos, end, self, field_dict) - return pos - cls._InternalParse = InternalParse - - -def _AddIsInitializedMethod(message_descriptor, cls): - """Adds the IsInitialized and FindInitializationError methods to the - protocol message class.""" - - required_fields = [field for field in message_descriptor.fields - if field.label == _FieldDescriptor.LABEL_REQUIRED] - - def IsInitialized(self, errors=None): - """Checks if all required fields of a message are set. - - Args: - errors: A list which, if provided, will be populated with the field - paths of all missing required fields. - - Returns: - True iff the specified message has all required fields set. - """ - - # Performance is critical so we avoid HasField() and ListFields(). - - for field in required_fields: - if (field not in self._fields or - (field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and - not self._fields[field]._is_present_in_parent)): - if errors is not None: - errors.extend(self.FindInitializationErrors()) - return False - - for field, value in self._fields.iteritems(): - if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - if field.label == _FieldDescriptor.LABEL_REPEATED: - for element in value: - if not element.IsInitialized(): - if errors is not None: - errors.extend(self.FindInitializationErrors()) - return False - elif value._is_present_in_parent and not value.IsInitialized(): - if errors is not None: - errors.extend(self.FindInitializationErrors()) - return False - - return True - - cls.IsInitialized = IsInitialized - - def FindInitializationErrors(self): - """Finds required fields which are not initialized. - - Returns: - A list of strings. Each string is a path to an uninitialized field from - the top-level message, e.g. "foo.bar[5].baz". - """ - - errors = [] # simplify things - - for field in required_fields: - if not self.HasField(field.name): - errors.append(field.name) - - for field, value in self.ListFields(): - if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - if field.is_extension: - name = "(%s)" % field.full_name - else: - name = field.name - - if field.label == _FieldDescriptor.LABEL_REPEATED: - for i in xrange(len(value)): - element = value[i] - prefix = "%s[%d]." % (name, i) - sub_errors = element.FindInitializationErrors() - errors += [ prefix + error for error in sub_errors ] - else: - prefix = name + "." - sub_errors = value.FindInitializationErrors() - errors += [ prefix + error for error in sub_errors ] - - return errors - - cls.FindInitializationErrors = FindInitializationErrors - - -def _AddMergeFromMethod(cls): - LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED - CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE - - def MergeFrom(self, msg): - assert msg is not self - self._Modified() - - fields = self._fields - - for field, value in msg._fields.iteritems(): - if field.label == LABEL_REPEATED or field.cpp_type == CPPTYPE_MESSAGE: - field_value = fields.get(field) - if field_value is None: - # Construct a new object to represent this field. - field_value = field._default_constructor(self) - fields[field] = field_value - field_value.MergeFrom(value) - else: - self._fields[field] = value - cls.MergeFrom = MergeFrom - - -def _AddMessageMethods(message_descriptor, cls): - """Adds implementations of all Message methods to cls.""" - _AddListFieldsMethod(message_descriptor, cls) - _AddHasFieldMethod(message_descriptor, cls) - _AddClearFieldMethod(message_descriptor, cls) - if message_descriptor.is_extendable: - _AddClearExtensionMethod(cls) - _AddHasExtensionMethod(cls) - _AddClearMethod(message_descriptor, cls) - _AddEqualsMethod(message_descriptor, cls) - _AddStrMethod(message_descriptor, cls) - _AddSetListenerMethod(cls) - _AddByteSizeMethod(message_descriptor, cls) - _AddSerializeToStringMethod(message_descriptor, cls) - _AddSerializePartialToStringMethod(message_descriptor, cls) - _AddMergeFromStringMethod(message_descriptor, cls) - _AddIsInitializedMethod(message_descriptor, cls) - _AddMergeFromMethod(cls) - - -def _AddPrivateHelperMethods(cls): - """Adds implementation of private helper methods to cls.""" - - def Modified(self): - """Sets the _cached_byte_size_dirty bit to true, - and propagates this to our listener iff this was a state change. - """ - - # Note: Some callers check _cached_byte_size_dirty before calling - # _Modified() as an extra optimization. So, if this method is ever - # changed such that it does stuff even when _cached_byte_size_dirty is - # already true, the callers need to be updated. - if not self._cached_byte_size_dirty: - self._cached_byte_size_dirty = True - self._listener_for_children.dirty = True - self._is_present_in_parent = True - self._listener.Modified() - - cls._Modified = Modified - cls.SetInParent = Modified - - -class _Listener(object): - - """MessageListener implementation that a parent message registers with its - child message. - - In order to support semantics like: - - foo.bar.baz.qux = 23 - assert foo.HasField('bar') - - ...child objects must have back references to their parents. - This helper class is at the heart of this support. - """ - - def __init__(self, parent_message): - """Args: - parent_message: The message whose _Modified() method we should call when - we receive Modified() messages. - """ - # This listener establishes a back reference from a child (contained) object - # to its parent (containing) object. We make this a weak reference to avoid - # creating cyclic garbage when the client finishes with the 'parent' object - # in the tree. - if isinstance(parent_message, weakref.ProxyType): - self._parent_message_weakref = parent_message - else: - self._parent_message_weakref = weakref.proxy(parent_message) - - # As an optimization, we also indicate directly on the listener whether - # or not the parent message is dirty. This way we can avoid traversing - # up the tree in the common case. - self.dirty = False - - def Modified(self): - if self.dirty: - return - try: - # Propagate the signal to our parents iff this is the first field set. - self._parent_message_weakref._Modified() - except ReferenceError: - # We can get here if a client has kept a reference to a child object, - # and is now setting a field on it, but the child's parent has been - # garbage-collected. This is not an error. - pass - - -# TODO(robinson): Move elsewhere? This file is getting pretty ridiculous... -# TODO(robinson): Unify error handling of "unknown extension" crap. -# TODO(robinson): Support iteritems()-style iteration over all -# extensions with the "has" bits turned on? -class _ExtensionDict(object): - - """Dict-like container for supporting an indexable "Extensions" - field on proto instances. - - Note that in all cases we expect extension handles to be - FieldDescriptors. + descriptor: A descriptor.Descriptor object describing the protobuf. + Returns: + The Message class object described by the descriptor. """ + attributes = {} + for name, nested_type in descriptor.nested_types_by_name.items(): + attributes[name] = MakeClass(nested_type) - def __init__(self, extended_message): - """extended_message: Message instance for which we are the Extensions dict. - """ - - self._extended_message = extended_message - - def __getitem__(self, extension_handle): - """Returns the current value of the given extension handle.""" - - _VerifyExtensionHandle(self._extended_message, extension_handle) - - result = self._extended_message._fields.get(extension_handle) - if result is not None: - return result - - if extension_handle.label == _FieldDescriptor.LABEL_REPEATED: - result = extension_handle._default_constructor(self._extended_message) - elif extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - result = extension_handle.message_type._concrete_class() - try: - result._SetListener(self._extended_message._listener_for_children) - except ReferenceError: - pass - else: - # Singular scalar -- just return the default without inserting into the - # dict. - return extension_handle.default_value - - # Atomically check if another thread has preempted us and, if not, swap - # in the new object we just created. If someone has preempted us, we - # take that object and discard ours. - # WARNING: We are relying on setdefault() being atomic. This is true - # in CPython but we haven't investigated others. This warning appears - # in several other locations in this file. - result = self._extended_message._fields.setdefault( - extension_handle, result) - - return result - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return False + attributes[GeneratedProtocolMessageType._DESCRIPTOR_KEY] = descriptor - my_fields = self._extended_message.ListFields() - other_fields = other._extended_message.ListFields() - - # Get rid of non-extension fields. - my_fields = [ field for field in my_fields if field.is_extension ] - other_fields = [ field for field in other_fields if field.is_extension ] - - return my_fields == other_fields - - def __ne__(self, other): - return not self == other - - # Note that this is only meaningful for non-repeated, scalar extension - # fields. Note also that we may have to call _Modified() when we do - # successfully set a field this way, to set any necssary "has" bits in the - # ancestors of the extended message. - def __setitem__(self, extension_handle, value): - """If extension_handle specifies a non-repeated, scalar extension - field, sets the value of that field. - """ - - _VerifyExtensionHandle(self._extended_message, extension_handle) - - if (extension_handle.label == _FieldDescriptor.LABEL_REPEATED or - extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE): - raise TypeError( - 'Cannot assign to extension "%s" because it is a repeated or ' - 'composite type.' % extension_handle.full_name) - - # It's slightly wasteful to lookup the type checker each time, - # but we expect this to be a vanishingly uncommon case anyway. - type_checker = type_checkers.GetTypeChecker( - extension_handle.cpp_type, extension_handle.type) - type_checker.CheckValue(value) - self._extended_message._fields[extension_handle] = value - self._extended_message._Modified() - - def _FindExtensionByName(self, name): - """Tries to find a known extension with the specified name. - - Args: - name: Extension full name. - - Returns: - Extension field descriptor. - """ - return self._extended_message._extensions_by_name.get(name, None) + return GeneratedProtocolMessageType(str(descriptor.name), (message.Message,), + attributes) diff --git a/python/google/protobuf/symbol_database.py b/python/google/protobuf/symbol_database.py new file mode 100644 index 0000000..7466fec --- /dev/null +++ b/python/google/protobuf/symbol_database.py @@ -0,0 +1,185 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""A database of Python protocol buffer generated symbols. + +SymbolDatabase makes it easy to create new instances of a registered type, given +only the type's protocol buffer symbol name. Once all symbols are registered, +they can be accessed using either the MessageFactory interface which +SymbolDatabase exposes, or the DescriptorPool interface of the underlying +pool. + +Example usage: + + db = symbol_database.SymbolDatabase() + + # Register symbols of interest, from one or multiple files. + db.RegisterFileDescriptor(my_proto_pb2.DESCRIPTOR) + db.RegisterMessage(my_proto_pb2.MyMessage) + db.RegisterEnumDescriptor(my_proto_pb2.MyEnum.DESCRIPTOR) + + # The database can be used as a MessageFactory, to generate types based on + # their name: + types = db.GetMessages(['my_proto.proto']) + my_message_instance = types['MyMessage']() + + # The database's underlying descriptor pool can be queried, so it's not + # necessary to know a type's filename to be able to generate it: + filename = db.pool.FindFileContainingSymbol('MyMessage') + my_message_instance = db.GetMessages([filename])['MyMessage']() + + # This functionality is also provided directly via a convenience method: + my_message_instance = db.GetSymbol('MyMessage')() +""" + + +from google.protobuf import descriptor_pool + + +class SymbolDatabase(object): + """A database of Python generated symbols. + + SymbolDatabase also models message_factory.MessageFactory. + + The symbol database can be used to keep a global registry of all protocol + buffer types used within a program. + """ + + def __init__(self): + """Constructor.""" + + self._symbols = {} + self._symbols_by_file = {} + self.pool = descriptor_pool.DescriptorPool() + + def RegisterMessage(self, message): + """Registers the given message type in the local database. + + Args: + message: a message.Message, to be registered. + + Returns: + The provided message. + """ + + desc = message.DESCRIPTOR + self._symbols[desc.full_name] = message + if desc.file.name not in self._symbols_by_file: + self._symbols_by_file[desc.file.name] = {} + self._symbols_by_file[desc.file.name][desc.full_name] = message + self.pool.AddDescriptor(desc) + return message + + def RegisterEnumDescriptor(self, enum_descriptor): + """Registers the given enum descriptor in the local database. + + Args: + enum_descriptor: a descriptor.EnumDescriptor. + + Returns: + The provided descriptor. + """ + self.pool.AddEnumDescriptor(enum_descriptor) + return enum_descriptor + + def RegisterFileDescriptor(self, file_descriptor): + """Registers the given file descriptor in the local database. + + Args: + file_descriptor: a descriptor.FileDescriptor. + + Returns: + The provided descriptor. + """ + self.pool.AddFileDescriptor(file_descriptor) + + def GetSymbol(self, symbol): + """Tries to find a symbol in the local database. + + Currently, this method only returns message.Message instances, however, if + may be extended in future to support other symbol types. + + Args: + symbol: A str, a protocol buffer symbol. + + Returns: + A Python class corresponding to the symbol. + + Raises: + KeyError: if the symbol could not be found. + """ + + return self._symbols[symbol] + + def GetPrototype(self, descriptor): + """Builds a proto2 message class based on the passed in descriptor. + + Passing a descriptor with a fully qualified name matching a previous + invocation will cause the same class to be returned. + + Args: + descriptor: The descriptor to build from. + + Returns: + A class describing the passed in descriptor. + """ + + return self.GetSymbol(descriptor.full_name) + + def GetMessages(self, files): + """Gets all the messages from a specified file. + + This will find and resolve dependencies, failing if they are not registered + in the symbol database. + + + Args: + files: The file names to extract messages from. + + Returns: + A dictionary mapping proto names to the message classes. This will include + any dependent messages as well as any messages defined in the same file as + a specified message. + + Raises: + KeyError: if a file could not be found. + """ + + result = {} + for f in files: + result.update(self._symbols_by_file[f]) + return result + +_DEFAULT = SymbolDatabase() + + +def Default(): + """Returns the default SymbolDatabase.""" + return _DEFAULT diff --git a/python/google/protobuf/text_encoding.py b/python/google/protobuf/text_encoding.py new file mode 100644 index 0000000..ed0aabf --- /dev/null +++ b/python/google/protobuf/text_encoding.py @@ -0,0 +1,110 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +#PY25 compatible for GAE. +# +"""Encoding related utilities.""" + +import re +import sys ##PY25 + +# Lookup table for utf8 +_cescape_utf8_to_str = [chr(i) for i in xrange(0, 256)] +_cescape_utf8_to_str[9] = r'\t' # optional escape +_cescape_utf8_to_str[10] = r'\n' # optional escape +_cescape_utf8_to_str[13] = r'\r' # optional escape +_cescape_utf8_to_str[39] = r"\'" # optional escape + +_cescape_utf8_to_str[34] = r'\"' # necessary escape +_cescape_utf8_to_str[92] = r'\\' # necessary escape + +# Lookup table for non-utf8, with necessary escapes at (o >= 127 or o < 32) +_cescape_byte_to_str = ([r'\%03o' % i for i in xrange(0, 32)] + + [chr(i) for i in xrange(32, 127)] + + [r'\%03o' % i for i in xrange(127, 256)]) +_cescape_byte_to_str[9] = r'\t' # optional escape +_cescape_byte_to_str[10] = r'\n' # optional escape +_cescape_byte_to_str[13] = r'\r' # optional escape +_cescape_byte_to_str[39] = r"\'" # optional escape + +_cescape_byte_to_str[34] = r'\"' # necessary escape +_cescape_byte_to_str[92] = r'\\' # necessary escape + + +def CEscape(text, as_utf8): + """Escape a bytes string for use in an ascii protocol buffer. + + text.encode('string_escape') does not seem to satisfy our needs as it + encodes unprintable characters using two-digit hex escapes whereas our + C++ unescaping function allows hex escapes to be any length. So, + "\0011".encode('string_escape') ends up being "\\x011", which will be + decoded in C++ as a single-character string with char code 0x11. + + Args: + text: A byte string to be escaped + as_utf8: Specifies if result should be returned in UTF-8 encoding + Returns: + Escaped string + """ + # PY3 hack: make Ord work for str and bytes: + # //platforms/networking/data uses unicode here, hence basestring. + Ord = ord if isinstance(text, basestring) else lambda x: x + if as_utf8: + return ''.join(_cescape_utf8_to_str[Ord(c)] for c in text) + return ''.join(_cescape_byte_to_str[Ord(c)] for c in text) + + +_CUNESCAPE_HEX = re.compile(r'(\\+)x([0-9a-fA-F])(?![0-9a-fA-F])') +_cescape_highbit_to_str = ([chr(i) for i in range(0, 127)] + + [r'\%03o' % i for i in range(127, 256)]) + + +def CUnescape(text): + """Unescape a text string with C-style escape sequences to UTF-8 bytes.""" + + def ReplaceHex(m): + # Only replace the match if the number of leading back slashes is odd. i.e. + # the slash itself is not escaped. + if len(m.group(1)) & 1: + return m.group(1) + 'x0' + m.group(2) + return m.group(0) + + # This is required because the 'string_escape' encoding doesn't + # allow single-digit hex escapes (like '\xf'). + result = _CUNESCAPE_HEX.sub(ReplaceHex, text) + + if sys.version_info[0] < 3: ##PY25 +##!PY25 if str is bytes: # PY2 + return result.decode('string_escape') + result = ''.join(_cescape_highbit_to_str[ord(c)] for c in result) + return (result.encode('ascii') # Make it bytes to allow decode. + .decode('unicode_escape') + # Make it bytes again to return the proper type. + .encode('raw_unicode_escape')) diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py index cc6ac90..50f76f2 100755 --- a/python/google/protobuf/text_format.py +++ b/python/google/protobuf/text_format.py @@ -28,6 +28,10 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#PY25 compatible for GAE. +# +# Copyright 2007 Google Inc. All Rights Reserved. + """Contains routines for printing protocol messages in text format.""" __author__ = 'kenton@google.com (Kenton Varda)' @@ -35,46 +39,92 @@ __author__ = 'kenton@google.com (Kenton Varda)' import cStringIO import re -from collections import deque from google.protobuf.internal import type_checkers from google.protobuf import descriptor +from google.protobuf import text_encoding + +__all__ = ['MessageToString', 'PrintMessage', 'PrintField', + 'PrintFieldValue', 'Merge'] -__all__ = [ 'MessageToString', 'PrintMessage', 'PrintField', - 'PrintFieldValue', 'Merge' ] +_INTEGER_CHECKERS = (type_checkers.Uint32ValueChecker(), + type_checkers.Int32ValueChecker(), + type_checkers.Uint64ValueChecker(), + type_checkers.Int64ValueChecker()) +_FLOAT_INFINITY = re.compile('-?inf(?:inity)?f?', re.IGNORECASE) +_FLOAT_NAN = re.compile('nanf?', re.IGNORECASE) +_FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT, + descriptor.FieldDescriptor.CPPTYPE_DOUBLE]) -# Infinity and NaN are not explicitly supported by Python pre-2.6, and -# float('inf') does not work on Windows (pre-2.6). -_INFINITY = 1e10000 # overflows, thus will actually be infinity. -_NAN = _INFINITY * 0 +class Error(Exception): + """Top-level module error for text_format.""" -class ParseError(Exception): + +class ParseError(Error): """Thrown in case of ASCII parsing error.""" -def MessageToString(message): +def MessageToString(message, as_utf8=False, as_one_line=False, + pointy_brackets=False, use_index_order=False, + float_format=None): + """Convert protobuf message to text format. + + Floating point values can be formatted compactly with 15 digits of + precision (which is the most that IEEE 754 "double" can guarantee) + using float_format='.15g'. + + Args: + message: The protocol buffers message. + as_utf8: Produce text output in UTF8 format. + as_one_line: Don't introduce newlines between fields. + pointy_brackets: If True, use angle brackets instead of curly braces for + nesting. + use_index_order: If True, print fields of a proto message using the order + defined in source code instead of the field number. By default, use the + field number order. + float_format: If set, use this to specify floating point number formatting + (per the "Format Specification Mini-Language"); otherwise, str() is used. + + Returns: + A string of the text formatted protocol buffer message. + """ out = cStringIO.StringIO() - PrintMessage(message, out) + PrintMessage(message, out, as_utf8=as_utf8, as_one_line=as_one_line, + pointy_brackets=pointy_brackets, + use_index_order=use_index_order, + float_format=float_format) result = out.getvalue() out.close() + if as_one_line: + return result.rstrip() return result -def PrintMessage(message, out, indent = 0): - for field, value in message.ListFields(): +def PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False, + pointy_brackets=False, use_index_order=False, + float_format=None): + fields = message.ListFields() + if use_index_order: + fields.sort(key=lambda x: x[0].index) + for field, value in fields: if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: for element in value: - PrintField(field, element, out, indent) + PrintField(field, element, out, indent, as_utf8, as_one_line, + pointy_brackets=pointy_brackets, + float_format=float_format) else: - PrintField(field, value, out, indent) + PrintField(field, value, out, indent, as_utf8, as_one_line, + pointy_brackets=pointy_brackets, + float_format=float_format) -def PrintField(field, value, out, indent = 0): +def PrintField(field, value, out, indent=0, as_utf8=False, as_one_line=False, + pointy_brackets=False, float_format=None): """Print a single field name/value pair. For repeated fields, the value should be a single element.""" - out.write(' ' * indent); + out.write(' ' * indent) if field.is_extension: out.write('[') if (field.containing_type.GetOptions().message_set_wire_format and @@ -96,54 +146,168 @@ def PrintField(field, value, out, indent = 0): # don't include it. out.write(': ') - PrintFieldValue(field, value, out, indent) - out.write('\n') + PrintFieldValue(field, value, out, indent, as_utf8, as_one_line, + pointy_brackets=pointy_brackets, + float_format=float_format) + if as_one_line: + out.write(' ') + else: + out.write('\n') -def PrintFieldValue(field, value, out, indent = 0): +def PrintFieldValue(field, value, out, indent=0, as_utf8=False, + as_one_line=False, pointy_brackets=False, + float_format=None): """Print a single field value (not including name). For repeated fields, the value should be a single element.""" + if pointy_brackets: + openb = '<' + closeb = '>' + else: + openb = '{' + closeb = '}' + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: - out.write(' {\n') - PrintMessage(value, out, indent + 2) - out.write(' ' * indent + '}') + if as_one_line: + out.write(' %s ' % openb) + PrintMessage(value, out, indent, as_utf8, as_one_line, + pointy_brackets=pointy_brackets, + float_format=float_format) + out.write(closeb) + else: + out.write(' %s\n' % openb) + PrintMessage(value, out, indent + 2, as_utf8, as_one_line, + pointy_brackets=pointy_brackets, + float_format=float_format) + out.write(' ' * indent + closeb) elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: - out.write(field.enum_type.values_by_number[value].name) + enum_value = field.enum_type.values_by_number.get(value, None) + if enum_value is not None: + out.write(enum_value.name) + else: + out.write(str(value)) elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING: out.write('\"') - out.write(_CEscape(value)) + if isinstance(value, unicode): + out_value = value.encode('utf-8') + else: + out_value = value + if field.type == descriptor.FieldDescriptor.TYPE_BYTES: + # We need to escape non-UTF8 chars in TYPE_BYTES field. + out_as_utf8 = False + else: + out_as_utf8 = as_utf8 + out.write(text_encoding.CEscape(out_value, out_as_utf8)) out.write('\"') elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL: if value: - out.write("true") + out.write('true') else: - out.write("false") + out.write('false') + elif field.cpp_type in _FLOAT_TYPES and float_format is not None: + out.write('{1:{0}}'.format(float_format, value)) else: out.write(str(value)) +def _ParseOrMerge(lines, message, allow_multiple_scalars): + """Converts an ASCII representation of a protocol message into a message. + + Args: + lines: Lines of a message's ASCII representation. + message: A protocol buffer message to merge into. + allow_multiple_scalars: Determines if repeated values for a non-repeated + field are permitted, e.g., the string "foo: 1 foo: 2" for a + required/optional field named "foo". + + Raises: + ParseError: On ASCII parsing problems. + """ + tokenizer = _Tokenizer(lines) + while not tokenizer.AtEnd(): + _MergeField(tokenizer, message, allow_multiple_scalars) + + +def Parse(text, message): + """Parses an ASCII representation of a protocol message into a message. + + Args: + text: Message ASCII representation. + message: A protocol buffer message to merge into. + + Returns: + The same message passed as argument. + + Raises: + ParseError: On ASCII parsing problems. + """ + if not isinstance(text, str): text = text.decode('utf-8') + return ParseLines(text.split('\n'), message) + + def Merge(text, message): - """Merges an ASCII representation of a protocol message into a message. + """Parses an ASCII representation of a protocol message into a message. + + Like Parse(), but allows repeated values for a non-repeated field, and uses + the last one. Args: text: Message ASCII representation. message: A protocol buffer message to merge into. + Returns: + The same message passed as argument. + Raises: ParseError: On ASCII parsing problems. """ - tokenizer = _Tokenizer(text) - while not tokenizer.AtEnd(): - _MergeField(tokenizer, message) + return MergeLines(text.split('\n'), message) + + +def ParseLines(lines, message): + """Parses an ASCII representation of a protocol message into a message. + + Args: + lines: An iterable of lines of a message's ASCII representation. + message: A protocol buffer message to merge into. + + Returns: + The same message passed as argument. + + Raises: + ParseError: On ASCII parsing problems. + """ + _ParseOrMerge(lines, message, False) + return message + + +def MergeLines(lines, message): + """Parses an ASCII representation of a protocol message into a message. + + Args: + lines: An iterable of lines of a message's ASCII representation. + message: A protocol buffer message to merge into. + + Returns: + The same message passed as argument. + Raises: + ParseError: On ASCII parsing problems. + """ + _ParseOrMerge(lines, message, True) + return message -def _MergeField(tokenizer, message): + +def _MergeField(tokenizer, message, allow_multiple_scalars): """Merges a single protocol message field into a message. Args: tokenizer: A tokenizer to parse the field name and values. message: A protocol message to record the data. + allow_multiple_scalars: Determines if repeated values for a non-repeated + field are permitted, e.g., the string "foo: 1 foo: 2" for a + required/optional field named "foo". Raises: ParseError: In case of ASCII parsing problems. @@ -159,7 +323,9 @@ def _MergeField(tokenizer, message): raise tokenizer.ParseErrorPreviousToken( 'Message type "%s" does not have extensions.' % message_descriptor.full_name) + # pylint: disable=protected-access field = message.Extensions._FindExtensionByName(name) + # pylint: enable=protected-access if not field: raise tokenizer.ParseErrorPreviousToken( 'Extension "%s" not registered.' % name) @@ -208,23 +374,31 @@ def _MergeField(tokenizer, message): sub_message = message.Extensions[field] else: sub_message = getattr(message, field.name) - sub_message.SetInParent() + sub_message.SetInParent() while not tokenizer.TryConsume(end_token): if tokenizer.AtEnd(): raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token)) - _MergeField(tokenizer, sub_message) + _MergeField(tokenizer, sub_message, allow_multiple_scalars) else: - _MergeScalarField(tokenizer, message, field) + _MergeScalarField(tokenizer, message, field, allow_multiple_scalars) + + # For historical reasons, fields may optionally be separated by commas or + # semicolons. + if not tokenizer.TryConsume(','): + tokenizer.TryConsume(';') -def _MergeScalarField(tokenizer, message, field): +def _MergeScalarField(tokenizer, message, field, allow_multiple_scalars): """Merges a single protocol message scalar field into a message. Args: tokenizer: A tokenizer to parse the field value. message: A protocol message to record the data. field: The descriptor of the field to be merged. + allow_multiple_scalars: Determines if repeated values for a non-repeated + field are permitted, e.g., the string "foo: 1 foo: 2" for a + required/optional field named "foo". Raises: ParseError: In case of ASCII parsing problems. @@ -257,24 +431,7 @@ def _MergeScalarField(tokenizer, message, field): elif field.type == descriptor.FieldDescriptor.TYPE_BYTES: value = tokenizer.ConsumeByteString() elif field.type == descriptor.FieldDescriptor.TYPE_ENUM: - # Enum can be specified by a number (the enum value), or by - # a string literal (the enum name). - enum_descriptor = field.enum_type - if tokenizer.LookingAtInteger(): - number = tokenizer.ConsumeInt32() - enum_value = enum_descriptor.values_by_number.get(number, None) - if enum_value is None: - raise tokenizer.ParseErrorPreviousToken( - 'Enum type "%s" has no value with number %d.' % ( - enum_descriptor.full_name, number)) - else: - identifier = tokenizer.ConsumeIdentifier() - enum_value = enum_descriptor.values_by_name.get(identifier, None) - if enum_value is None: - raise tokenizer.ParseErrorPreviousToken( - 'Enum type "%s" has no value named %s.' % ( - enum_descriptor.full_name, identifier)) - value = enum_value.number + value = tokenizer.ConsumeEnum(field) else: raise RuntimeError('Unknown field type %d' % field.type) @@ -285,9 +442,19 @@ def _MergeScalarField(tokenizer, message, field): getattr(message, field.name).append(value) else: if field.is_extension: - message.Extensions[field] = value + if not allow_multiple_scalars and message.HasExtension(field): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" extensions.' % + (message.DESCRIPTOR.full_name, field.full_name)) + else: + message.Extensions[field] = value else: - setattr(message, field.name, value) + if not allow_multiple_scalars and message.HasField(field.name): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" fields.' % + (message.DESCRIPTOR.full_name, field.name)) + else: + setattr(message, field.name, value) class _Tokenizer(object): @@ -305,26 +472,19 @@ class _Tokenizer(object): '[0-9+-][0-9a-zA-Z_.+-]*|' # a number '\"([^\"\n\\\\]|\\\\.)*(\"|\\\\?$)|' # a double-quoted string '\'([^\'\n\\\\]|\\\\.)*(\'|\\\\?$)') # a single-quoted string - _IDENTIFIER = re.compile('\w+') - _INTEGER_CHECKERS = [type_checkers.Uint32ValueChecker(), - type_checkers.Int32ValueChecker(), - type_checkers.Uint64ValueChecker(), - type_checkers.Int64ValueChecker()] - _FLOAT_INFINITY = re.compile('-?inf(inity)?f?', re.IGNORECASE) - _FLOAT_NAN = re.compile("nanf?", re.IGNORECASE) - - def __init__(self, text_message): - self._text_message = text_message + _IDENTIFIER = re.compile(r'\w+') + def __init__(self, lines): self._position = 0 self._line = -1 self._column = 0 self._token_start = None self.token = '' - self._lines = deque(text_message.split('\n')) + self._lines = iter(lines) self._current_line = '' self._previous_line = 0 self._previous_column = 0 + self._more_lines = True self._SkipWhitespace() self.NextToken() @@ -334,25 +494,27 @@ class _Tokenizer(object): Returns: True iff the end was reached. """ - return not self._lines and not self._current_line + return not self.token def _PopLine(self): - while not self._current_line: - if not self._lines: + while len(self._current_line) <= self._column: + try: + self._current_line = self._lines.next() + except StopIteration: self._current_line = '' + self._more_lines = False return - self._line += 1 - self._column = 0 - self._current_line = self._lines.popleft() + else: + self._line += 1 + self._column = 0 def _SkipWhitespace(self): while True: self._PopLine() - match = re.match(self._WHITESPACE, self._current_line) + match = self._WHITESPACE.match(self._current_line, self._column) if not match: break length = len(match.group(0)) - self._current_line = self._current_line[length:] self._column += length def TryConsume(self, token): @@ -381,17 +543,6 @@ class _Tokenizer(object): if not self.TryConsume(token): raise self._ParseError('Expected "%s".' % token) - def LookingAtInteger(self): - """Checks if the current token is an integer. - - Returns: - True iff the current token is an integer. - """ - if not self.token: - return False - c = self.token[0] - return (c >= '0' and c <= '9') or c == '-' or c == '+' - def ConsumeIdentifier(self): """Consumes protocol message field identifier. @@ -402,7 +553,7 @@ class _Tokenizer(object): ParseError: If an identifier couldn't be consumed. """ result = self.token - if not re.match(self._IDENTIFIER, result): + if not self._IDENTIFIER.match(result): raise self._ParseError('Expected identifier.') self.NextToken() return result @@ -417,9 +568,9 @@ class _Tokenizer(object): ParseError: If a signed 32bit integer couldn't be consumed. """ try: - result = self._ParseInteger(self.token, is_signed=True, is_long=False) + result = ParseInteger(self.token, is_signed=True, is_long=False) except ValueError, e: - raise self._IntegerParseError(e) + raise self._ParseError(str(e)) self.NextToken() return result @@ -433,9 +584,9 @@ class _Tokenizer(object): ParseError: If an unsigned 32bit integer couldn't be consumed. """ try: - result = self._ParseInteger(self.token, is_signed=False, is_long=False) + result = ParseInteger(self.token, is_signed=False, is_long=False) except ValueError, e: - raise self._IntegerParseError(e) + raise self._ParseError(str(e)) self.NextToken() return result @@ -449,9 +600,9 @@ class _Tokenizer(object): ParseError: If a signed 64bit integer couldn't be consumed. """ try: - result = self._ParseInteger(self.token, is_signed=True, is_long=True) + result = ParseInteger(self.token, is_signed=True, is_long=True) except ValueError, e: - raise self._IntegerParseError(e) + raise self._ParseError(str(e)) self.NextToken() return result @@ -465,9 +616,9 @@ class _Tokenizer(object): ParseError: If an unsigned 64bit integer couldn't be consumed. """ try: - result = self._ParseInteger(self.token, is_signed=False, is_long=True) + result = ParseInteger(self.token, is_signed=False, is_long=True) except ValueError, e: - raise self._IntegerParseError(e) + raise self._ParseError(str(e)) self.NextToken() return result @@ -480,21 +631,10 @@ class _Tokenizer(object): Raises: ParseError: If a floating point number couldn't be consumed. """ - text = self.token - if re.match(self._FLOAT_INFINITY, text): - self.NextToken() - if text.startswith('-'): - return -_INFINITY - return _INFINITY - - if re.match(self._FLOAT_NAN, text): - self.NextToken() - return _NAN - try: - result = float(text) + result = ParseFloat(self.token) except ValueError, e: - raise self._FloatParseError(e) + raise self._ParseError(str(e)) self.NextToken() return result @@ -507,14 +647,12 @@ class _Tokenizer(object): Raises: ParseError: If a boolean value couldn't be consumed. """ - if self.token == 'true': - self.NextToken() - return True - elif self.token == 'false': - self.NextToken() - return False - else: - raise self._ParseError('Expected "true" or "false".') + try: + result = ParseBool(self.token) + except ValueError, e: + raise self._ParseError(str(e)) + self.NextToken() + return result def ConsumeString(self): """Consumes a string value. @@ -525,7 +663,11 @@ class _Tokenizer(object): Raises: ParseError: If a string value couldn't be consumed. """ - return unicode(self.ConsumeByteString(), 'utf-8') + the_bytes = self.ConsumeByteString() + try: + return unicode(the_bytes, 'utf-8') + except UnicodeDecodeError, e: + raise self._StringParseError(e) def ConsumeByteString(self): """Consumes a byte array value. @@ -536,10 +678,11 @@ class _Tokenizer(object): Raises: ParseError: If a byte array value couldn't be consumed. """ - list = [self._ConsumeSingleByteString()] - while len(self.token) > 0 and self.token[0] in ('\'', '"'): - list.append(self._ConsumeSingleByteString()) - return "".join(list) + the_list = [self._ConsumeSingleByteString()] + while self.token and self.token[0] in ('\'', '"'): + the_list.append(self._ConsumeSingleByteString()) + return ''.encode('latin1').join(the_list) ##PY25 +##!PY25 return b''.join(the_list) def _ConsumeSingleByteString(self): """Consume one token of a string literal. @@ -550,48 +693,24 @@ class _Tokenizer(object): """ text = self.token if len(text) < 1 or text[0] not in ('\'', '"'): - raise self._ParseError('Exptected string.') + raise self._ParseError('Expected string.') if len(text) < 2 or text[-1] != text[0]: raise self._ParseError('String missing ending quote.') try: - result = _CUnescape(text[1:-1]) + result = text_encoding.CUnescape(text[1:-1]) except ValueError, e: raise self._ParseError(str(e)) self.NextToken() return result - def _ParseInteger(self, text, is_signed=False, is_long=False): - """Parses an integer. - - Args: - text: The text to parse. - is_signed: True if a signed integer must be parsed. - is_long: True if a long integer must be parsed. - - Returns: - The integer value. - - Raises: - ValueError: Thrown Iff the text is not a valid integer. - """ - pos = 0 - if text.startswith('-'): - pos += 1 - - base = 10 - if text.startswith('0x', pos) or text.startswith('0X', pos): - base = 16 - elif text.startswith('0', pos): - base = 8 - - # Do the actual parsing. Exception handling is propagated to caller. - result = int(text, base) - - # Check if the integer is sane. Exceptions handled by callers. - checker = self._INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)] - checker.CheckValue(result) + def ConsumeEnum(self, field): + try: + result = ParseEnum(field, self.token) + except ValueError, e: + raise self._ParseError(str(e)) + self.NextToken() return result def ParseErrorPreviousToken(self, message): @@ -611,63 +730,144 @@ class _Tokenizer(object): return ParseError('%d:%d : %s' % ( self._line + 1, self._column + 1, message)) - def _IntegerParseError(self, e): - return self._ParseError('Couldn\'t parse integer: ' + str(e)) - - def _FloatParseError(self, e): - return self._ParseError('Couldn\'t parse number: ' + str(e)) + def _StringParseError(self, e): + return self._ParseError('Couldn\'t parse string: ' + str(e)) def NextToken(self): """Reads the next meaningful token.""" self._previous_line = self._line self._previous_column = self._column - if self.AtEnd(): - self.token = '' - return + self._column += len(self.token) + self._SkipWhitespace() - # Make sure there is data to work on. - self._PopLine() + if not self._more_lines: + self.token = '' + return - match = re.match(self._TOKEN, self._current_line) + match = self._TOKEN.match(self._current_line, self._column) if match: token = match.group(0) - self._current_line = self._current_line[len(token):] self.token = token else: - self.token = self._current_line[0] - self._current_line = self._current_line[1:] - self._SkipWhitespace() + self.token = self._current_line[self._column] + + +def ParseInteger(text, is_signed=False, is_long=False): + """Parses an integer. + + Args: + text: The text to parse. + is_signed: True if a signed integer must be parsed. + is_long: True if a long integer must be parsed. + + Returns: + The integer value. + + Raises: + ValueError: Thrown Iff the text is not a valid integer. + """ + # Do the actual parsing. Exception handling is propagated to caller. + try: + # We force 32-bit values to int and 64-bit values to long to make + # alternate implementations where the distinction is more significant + # (e.g. the C++ implementation) simpler. + if is_long: + result = long(text, 0) + else: + result = int(text, 0) + except ValueError: + raise ValueError('Couldn\'t parse integer: %s' % text) + + # Check if the integer is sane. Exceptions handled by callers. + checker = _INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)] + checker.CheckValue(result) + return result + + +def ParseFloat(text): + """Parse a floating point number. + + Args: + text: Text to parse. + Returns: + The number parsed. -# text.encode('string_escape') does not seem to satisfy our needs as it -# encodes unprintable characters using two-digit hex escapes whereas our -# C++ unescaping function allows hex escapes to be any length. So, -# "\0011".encode('string_escape') ends up being "\\x011", which will be -# decoded in C++ as a single-character string with char code 0x11. -def _CEscape(text): - def escape(c): - o = ord(c) - if o == 10: return r"\n" # optional escape - if o == 13: return r"\r" # optional escape - if o == 9: return r"\t" # optional escape - if o == 39: return r"\'" # optional escape + Raises: + ValueError: If a floating point number couldn't be parsed. + """ + try: + # Assume Python compatible syntax. + return float(text) + except ValueError: + # Check alternative spellings. + if _FLOAT_INFINITY.match(text): + if text[0] == '-': + return float('-inf') + else: + return float('inf') + elif _FLOAT_NAN.match(text): + return float('nan') + else: + # assume '1.0f' format + try: + return float(text.rstrip('f')) + except ValueError: + raise ValueError('Couldn\'t parse float: %s' % text) + + +def ParseBool(text): + """Parse a boolean value. + + Args: + text: Text to parse. + + Returns: + Boolean values parsed - if o == 34: return r'\"' # necessary escape - if o == 92: return r"\\" # necessary escape + Raises: + ValueError: If text is not a valid boolean. + """ + if text in ('true', 't', '1'): + return True + elif text in ('false', 'f', '0'): + return False + else: + raise ValueError('Expected "true" or "false".') - if o >= 127 or o < 32: return "\\%03o" % o # necessary escapes - return c - return "".join([escape(c) for c in text]) +def ParseEnum(field, value): + """Parse an enum value. -_CUNESCAPE_HEX = re.compile('\\\\x([0-9a-fA-F]{2}|[0-9a-f-A-F])') + The value can be specified by a number (the enum value), or by + a string literal (the enum name). + Args: + field: Enum field descriptor. + value: String value. -def _CUnescape(text): - def ReplaceHex(m): - return chr(int(m.group(0)[2:], 16)) - # This is required because the 'string_escape' encoding doesn't - # allow single-digit hex escapes (like '\xf'). - result = _CUNESCAPE_HEX.sub(ReplaceHex, text) - return result.decode('string_escape') + Returns: + Enum value number. + + Raises: + ValueError: If the enum value could not be parsed. + """ + enum_descriptor = field.enum_type + try: + number = int(value, 0) + except ValueError: + # Identifier. + enum_value = enum_descriptor.values_by_name.get(value, None) + if enum_value is None: + raise ValueError( + 'Enum type "%s" has no value named %s.' % ( + enum_descriptor.full_name, value)) + else: + # Numeric value. + enum_value = enum_descriptor.values_by_number.get(number, None) + if enum_value is None: + raise ValueError( + 'Enum type "%s" has no value with number %d.' % ( + enum_descriptor.full_name, number)) + return enum_value.number diff --git a/python/setup.py b/python/setup.py index 7242dae..9441d0e 100755 --- a/python/setup.py +++ b/python/setup.py @@ -1,25 +1,41 @@ #! /usr/bin/python # # See README for usage instructions. +import sys +import os +import subprocess # We must use setuptools, not distutils, because we need to use the # namespace_packages option for the "google" package. -from ez_setup import use_setuptools -use_setuptools() - -from setuptools import setup +try: + from setuptools import setup, Extension +except ImportError: + try: + from ez_setup import use_setuptools + use_setuptools() + from setuptools import setup, Extension + except ImportError: + sys.stderr.write( + "Could not import setuptools; make sure you have setuptools or " + "ez_setup installed.\n") + raise +from distutils.command.clean import clean as _clean +from distutils.command.build_py import build_py as _build_py from distutils.spawn import find_executable -import sys -import os -import subprocess maintainer_email = "protobuf@googlegroups.com" # Find the Protocol Compiler. -if os.path.exists("../src/protoc"): +if 'PROTOC' in os.environ and os.path.exists(os.environ['PROTOC']): + protoc = os.environ['PROTOC'] +elif os.path.exists("../src/protoc"): protoc = "../src/protoc" elif os.path.exists("../src/protoc.exe"): protoc = "../src/protoc.exe" +elif os.path.exists("../vsprojects/Debug/protoc.exe"): + protoc = "../vsprojects/Debug/protoc.exe" +elif os.path.exists("../vsprojects/Release/protoc.exe"): + protoc = "../vsprojects/Release/protoc.exe" else: protoc = find_executable("protoc") @@ -30,14 +46,14 @@ def generate_proto(source): output = source.replace(".proto", "_pb2.py").replace("../src/", "") - if not os.path.exists(source): - print "Can't find required file: " + source - sys.exit(-1) - if (not os.path.exists(output) or (os.path.exists(source) and os.path.getmtime(source) > os.path.getmtime(output))): - print "Generating %s..." % output + print ("Generating %s..." % output) + + if not os.path.exists(source): + sys.stderr.write("Can't find required file: %s\n" % source) + sys.exit(-1) if protoc == None: sys.stderr.write( @@ -49,74 +65,131 @@ def generate_proto(source): if subprocess.call(protoc_command) != 0: sys.exit(-1) -def MakeTestSuite(): - # This is apparently needed on some systems to make sure that the tests - # work even if a previous version is already installed. - if 'google' in sys.modules: - del sys.modules['google'] - +def GenerateUnittestProtos(): generate_proto("../src/google/protobuf/unittest.proto") + generate_proto("../src/google/protobuf/unittest_custom_options.proto") generate_proto("../src/google/protobuf/unittest_import.proto") + generate_proto("../src/google/protobuf/unittest_import_public.proto") generate_proto("../src/google/protobuf/unittest_mset.proto") generate_proto("../src/google/protobuf/unittest_no_generic_services.proto") + generate_proto("google/protobuf/internal/descriptor_pool_test1.proto") + generate_proto("google/protobuf/internal/descriptor_pool_test2.proto") + generate_proto("google/protobuf/internal/test_bad_identifiers.proto") + generate_proto("google/protobuf/internal/missing_enum_values.proto") generate_proto("google/protobuf/internal/more_extensions.proto") + generate_proto("google/protobuf/internal/more_extensions_dynamic.proto") generate_proto("google/protobuf/internal/more_messages.proto") + generate_proto("google/protobuf/internal/factory_test1.proto") + generate_proto("google/protobuf/internal/factory_test2.proto") + generate_proto("google/protobuf/pyext/python.proto") +def MakeTestSuite(): + # Test C++ implementation import unittest - import google.protobuf.internal.generator_test as generator_test - import google.protobuf.internal.descriptor_test as descriptor_test - import google.protobuf.internal.reflection_test as reflection_test - import google.protobuf.internal.service_reflection_test \ - as service_reflection_test - import google.protobuf.internal.text_format_test as text_format_test - import google.protobuf.internal.wire_format_test as wire_format_test + import google.protobuf.pyext.descriptor_cpp2_test as descriptor_cpp2_test + import google.protobuf.pyext.message_factory_cpp2_test \ + as message_factory_cpp2_test + import google.protobuf.pyext.reflection_cpp2_generated_test \ + as reflection_cpp2_generated_test loader = unittest.defaultTestLoader suite = unittest.TestSuite() - for test in [ generator_test, - descriptor_test, - reflection_test, - service_reflection_test, - text_format_test, - wire_format_test ]: + for test in [ descriptor_cpp2_test, + message_factory_cpp2_test, + reflection_cpp2_generated_test]: suite.addTest(loader.loadTestsFromModule(test)) - return suite -if __name__ == '__main__': - # TODO(kenton): Integrate this into setuptools somehow? - if len(sys.argv) >= 2 and sys.argv[1] == "clean": - # Delete generated _pb2.py files and .pyc files in the code tree. +class clean(_clean): + def run(self): + # Delete generated files in the code tree. for (dirpath, dirnames, filenames) in os.walk("."): for filename in filenames: filepath = os.path.join(dirpath, filename) - if filepath.endswith("_pb2.py") or filepath.endswith(".pyc"): + if filepath.endswith("_pb2.py") or filepath.endswith(".pyc") or \ + filepath.endswith(".so") or filepath.endswith(".o") or \ + filepath.endswith('google/protobuf/compiler/__init__.py'): os.remove(filepath) - else: + # _clean is an old-style class, so super() doesn't work. + _clean.run(self) + +class build_py(_build_py): + def run(self): # Generate necessary .proto file if it doesn't exist. - # TODO(kenton): Maybe we should hook this into a distutils command? generate_proto("../src/google/protobuf/descriptor.proto") + generate_proto("../src/google/protobuf/compiler/plugin.proto") + GenerateUnittestProtos() + + # Make sure google.protobuf/** are valid packages. + for path in ['', 'internal/', 'compiler/', 'pyext/']: + try: + open('google/protobuf/%s__init__.py' % path, 'a').close() + except EnvironmentError: + pass + # _build_py is an old-style class, so super() doesn't work. + _build_py.run(self) + # TODO(mrovner): Subclass to run 2to3 on some files only. + # Tracing what https://wiki.python.org/moin/PortingPythonToPy3k's "Approach 2" + # section on how to get 2to3 to run on source files during install under + # Python 3. This class seems like a good place to put logic that calls + # python3's distutils.util.run_2to3 on the subset of the files we have in our + # release that are subject to conversion. + # See code reference in previous code review. + +if __name__ == '__main__': + ext_module_list = [] + cpp_impl = '--cpp_implementation' + if cpp_impl in sys.argv: + sys.argv.remove(cpp_impl) + # C++ implementation extension + ext_module_list.append(Extension( + "google.protobuf.pyext._message", + [ "google/protobuf/pyext/descriptor.cc", + "google/protobuf/pyext/message.cc", + "google/protobuf/pyext/extension_dict.cc", + "google/protobuf/pyext/repeated_scalar_container.cc", + "google/protobuf/pyext/repeated_composite_container.cc" ], + define_macros=[('GOOGLE_PROTOBUF_HAS_ONEOF', '1')], + include_dirs = [ ".", "../src"], + libraries = [ "protobuf" ], + library_dirs = [ '../src/.libs' ], + )) setup(name = 'protobuf', - version = '2.3.0', + version = '2.6.0', packages = [ 'google' ], namespace_packages = [ 'google' ], test_suite = 'setup.MakeTestSuite', + google_test_dir = "google/protobuf/internal", # Must list modules explicitly so that we don't install tests. py_modules = [ + 'google.protobuf.internal.api_implementation', 'google.protobuf.internal.containers', + 'google.protobuf.internal.cpp_message', 'google.protobuf.internal.decoder', 'google.protobuf.internal.encoder', + 'google.protobuf.internal.enum_type_wrapper', 'google.protobuf.internal.message_listener', + 'google.protobuf.internal.python_message', 'google.protobuf.internal.type_checkers', 'google.protobuf.internal.wire_format', 'google.protobuf.descriptor', 'google.protobuf.descriptor_pb2', + 'google.protobuf.compiler.plugin_pb2', 'google.protobuf.message', + 'google.protobuf.descriptor_database', + 'google.protobuf.descriptor_pool', + 'google.protobuf.message_factory', 'google.protobuf.reflection', 'google.protobuf.service', 'google.protobuf.service_reflection', - 'google.protobuf.text_format' ], + 'google.protobuf.symbol_database', + 'google.protobuf.text_encoding', + 'google.protobuf.text_format'], + cmdclass = { 'clean': clean, 'build_py': build_py }, + install_requires = ['setuptools'], + setup_requires = ['google-apputils'], + ext_modules = ext_module_list, url = 'http://code.google.com/p/protobuf/', maintainer = maintainer_email, maintainer_email = 'protobuf@googlegroups.com', diff --git a/src/Makefile.am b/src/Makefile.am index 4f82baf..4c69d47 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,56 +37,77 @@ CLEANFILES = $(protoc_outputs) unittest_proto_middleman \ MAINTAINERCLEANFILES = \ Makefile.in -nobase_include_HEADERS = \ - google/protobuf/stubs/common.h \ - google/protobuf/stubs/once.h \ - google/protobuf/descriptor.h \ - google/protobuf/descriptor.pb.h \ - google/protobuf/descriptor_database.h \ - google/protobuf/dynamic_message.h \ - google/protobuf/extension_set.h \ - google/protobuf/generated_message_util.h \ - google/protobuf/generated_message_reflection.h \ - google/protobuf/message.h \ - google/protobuf/message_lite.h \ - google/protobuf/reflection_ops.h \ - google/protobuf/repeated_field.h \ - google/protobuf/service.h \ - google/protobuf/text_format.h \ - google/protobuf/unknown_field_set.h \ - google/protobuf/wire_format.h \ - google/protobuf/wire_format_lite.h \ - google/protobuf/wire_format_lite_inl.h \ - google/protobuf/io/coded_stream.h \ - $(GZHEADERS) \ - google/protobuf/io/printer.h \ - google/protobuf/io/tokenizer.h \ - google/protobuf/io/zero_copy_stream.h \ - google/protobuf/io/zero_copy_stream_impl.h \ - google/protobuf/io/zero_copy_stream_impl_lite.h \ - google/protobuf/compiler/code_generator.h \ - google/protobuf/compiler/command_line_interface.h \ - google/protobuf/compiler/importer.h \ - google/protobuf/compiler/parser.h \ - google/protobuf/compiler/plugin.h \ - google/protobuf/compiler/plugin.pb.h \ - google/protobuf/compiler/cpp/cpp_generator.h \ - google/protobuf/compiler/java/java_generator.h \ - google/protobuf/compiler/javamicro/javamicro_generator.h \ - google/protobuf/compiler/javanano/javanano_generator.h \ +nobase_include_HEADERS = \ + google/protobuf/stubs/atomicops.h \ + google/protobuf/stubs/atomicops_internals_arm_gcc.h \ + google/protobuf/stubs/atomicops_internals_arm64_gcc.h \ + google/protobuf/stubs/atomicops_internals_arm_qnx.h \ + google/protobuf/stubs/atomicops_internals_atomicword_compat.h \ + google/protobuf/stubs/atomicops_internals_generic_gcc.h \ + google/protobuf/stubs/atomicops_internals_macosx.h \ + google/protobuf/stubs/atomicops_internals_mips_gcc.h \ + google/protobuf/stubs/atomicops_internals_pnacl.h \ + google/protobuf/stubs/atomicops_internals_tsan.h \ + google/protobuf/stubs/atomicops_internals_x86_gcc.h \ + google/protobuf/stubs/atomicops_internals_x86_msvc.h \ + google/protobuf/stubs/common.h \ + google/protobuf/stubs/platform_macros.h \ + google/protobuf/stubs/once.h \ + google/protobuf/stubs/stl_util.h \ + google/protobuf/stubs/template_util.h \ + google/protobuf/stubs/type_traits.h \ + google/protobuf/descriptor.h \ + google/protobuf/descriptor.pb.h \ + google/protobuf/descriptor_database.h \ + google/protobuf/dynamic_message.h \ + google/protobuf/extension_set.h \ + google/protobuf/generated_enum_reflection.h \ + google/protobuf/generated_message_util.h \ + google/protobuf/generated_message_reflection.h \ + google/protobuf/message.h \ + google/protobuf/message_lite.h \ + google/protobuf/reflection_ops.h \ + google/protobuf/repeated_field.h \ + google/protobuf/service.h \ + google/protobuf/text_format.h \ + google/protobuf/unknown_field_set.h \ + google/protobuf/wire_format.h \ + google/protobuf/wire_format_lite.h \ + google/protobuf/wire_format_lite_inl.h \ + google/protobuf/io/coded_stream.h \ + $(GZHEADERS) \ + google/protobuf/io/printer.h \ + google/protobuf/io/strtod.h \ + google/protobuf/io/tokenizer.h \ + google/protobuf/io/zero_copy_stream.h \ + google/protobuf/io/zero_copy_stream_impl.h \ + google/protobuf/io/zero_copy_stream_impl_lite.h \ + google/protobuf/compiler/code_generator.h \ + google/protobuf/compiler/command_line_interface.h \ + google/protobuf/compiler/importer.h \ + google/protobuf/compiler/parser.h \ + google/protobuf/compiler/plugin.h \ + google/protobuf/compiler/plugin.pb.h \ + google/protobuf/compiler/cpp/cpp_generator.h \ + google/protobuf/compiler/java/java_generator.h \ + google/protobuf/compiler/javamicro/javamicro_generator.h \ + google/protobuf/compiler/javanano/javanano_generator.h \ google/protobuf/compiler/python/python_generator.h lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS) -libprotobuf_lite_la_LDFLAGS = -version-info 6:0:0 -export-dynamic -no-undefined +libprotobuf_lite_la_LDFLAGS = -version-info 9:0:0 -export-dynamic -no-undefined libprotobuf_lite_la_SOURCES = \ + google/protobuf/stubs/atomicops_internals_x86_gcc.cc \ + google/protobuf/stubs/atomicops_internals_x86_msvc.cc \ google/protobuf/stubs/common.cc \ google/protobuf/stubs/once.cc \ - google/protobuf/stubs/hash.cc \ google/protobuf/stubs/hash.h \ - google/protobuf/stubs/map-util.h \ - google/protobuf/stubs/stl_util-inl.h \ + google/protobuf/stubs/map_util.h \ + google/protobuf/stubs/shared_ptr.h \ + google/protobuf/stubs/stringprintf.cc \ + google/protobuf/stubs/stringprintf.h \ google/protobuf/extension_set.cc \ google/protobuf/generated_message_util.cc \ google/protobuf/message_lite.cc \ @@ -98,7 +119,7 @@ libprotobuf_lite_la_SOURCES = \ google/protobuf/io/zero_copy_stream_impl_lite.cc libprotobuf_la_LIBADD = $(PTHREAD_LIBS) -libprotobuf_la_LDFLAGS = -version-info 6:0:0 -export-dynamic -no-undefined +libprotobuf_la_LDFLAGS = -version-info 9:0:0 -export-dynamic -no-undefined libprotobuf_la_SOURCES = \ $(libprotobuf_lite_la_SOURCES) \ google/protobuf/stubs/strutil.cc \ @@ -120,13 +141,14 @@ libprotobuf_la_SOURCES = \ google/protobuf/wire_format.cc \ google/protobuf/io/gzip_stream.cc \ google/protobuf/io/printer.cc \ + google/protobuf/io/strtod.cc \ google/protobuf/io/tokenizer.cc \ google/protobuf/io/zero_copy_stream_impl.cc \ google/protobuf/compiler/importer.cc \ google/protobuf/compiler/parser.cc libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la -libprotoc_la_LDFLAGS = -version-info 6:0:0 -export-dynamic -no-undefined +libprotoc_la_LDFLAGS = -version-info 9:0:0 -export-dynamic -no-undefined libprotoc_la_SOURCES = \ google/protobuf/compiler/code_generator.cc \ google/protobuf/compiler/command_line_interface.cc \ @@ -153,12 +175,15 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/cpp/cpp_message.h \ google/protobuf/compiler/cpp/cpp_message_field.cc \ google/protobuf/compiler/cpp/cpp_message_field.h \ + google/protobuf/compiler/cpp/cpp_options.h \ google/protobuf/compiler/cpp/cpp_primitive_field.cc \ google/protobuf/compiler/cpp/cpp_primitive_field.h \ google/protobuf/compiler/cpp/cpp_service.cc \ google/protobuf/compiler/cpp/cpp_service.h \ google/protobuf/compiler/cpp/cpp_string_field.cc \ google/protobuf/compiler/cpp/cpp_string_field.h \ + google/protobuf/compiler/java/java_context.cc \ + google/protobuf/compiler/java/java_context.h \ google/protobuf/compiler/java/java_enum.cc \ google/protobuf/compiler/java/java_enum.h \ google/protobuf/compiler/java/java_enum_field.cc \ @@ -170,16 +195,28 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/java/java_file.cc \ google/protobuf/compiler/java/java_file.h \ google/protobuf/compiler/java/java_generator.cc \ + google/protobuf/compiler/java/java_generator_factory.cc \ + google/protobuf/compiler/java/java_generator_factory.h \ google/protobuf/compiler/java/java_helpers.cc \ google/protobuf/compiler/java/java_helpers.h \ + google/protobuf/compiler/java/java_lazy_message_field.cc \ + google/protobuf/compiler/java/java_lazy_message_field.h \ google/protobuf/compiler/java/java_message.cc \ google/protobuf/compiler/java/java_message.h \ google/protobuf/compiler/java/java_message_field.cc \ google/protobuf/compiler/java/java_message_field.h \ + google/protobuf/compiler/java/java_name_resolver.cc \ + google/protobuf/compiler/java/java_name_resolver.h \ google/protobuf/compiler/java/java_primitive_field.cc \ google/protobuf/compiler/java/java_primitive_field.h \ + google/protobuf/compiler/java/java_shared_code_generator.cc \ + google/protobuf/compiler/java/java_shared_code_generator.h \ google/protobuf/compiler/java/java_service.cc \ google/protobuf/compiler/java/java_service.h \ + google/protobuf/compiler/java/java_string_field.cc \ + google/protobuf/compiler/java/java_string_field.h \ + google/protobuf/compiler/java/java_doc_comment.cc \ + google/protobuf/compiler/java/java_doc_comment.h \ google/protobuf/compiler/javamicro/javamicro_enum.cc \ google/protobuf/compiler/javamicro/javamicro_enum.h \ google/protobuf/compiler/javamicro/javamicro_enum_field.cc \ @@ -228,12 +265,14 @@ protoc_inputs = \ google/protobuf/unittest.proto \ google/protobuf/unittest_empty.proto \ google/protobuf/unittest_import.proto \ + google/protobuf/unittest_import_public.proto \ google/protobuf/unittest_mset.proto \ google/protobuf/unittest_optimize_for.proto \ google/protobuf/unittest_embed_optimize_for.proto \ google/protobuf/unittest_custom_options.proto \ google/protobuf/unittest_lite.proto \ google/protobuf/unittest_import_lite.proto \ + google/protobuf/unittest_import_public_lite.proto \ google/protobuf/unittest_lite_imports_nonlite.proto \ google/protobuf/unittest_no_generic_services.proto \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto @@ -244,9 +283,15 @@ EXTRA_DIST = \ google/protobuf/io/gzip_stream.h \ google/protobuf/io/gzip_stream_unittest.sh \ google/protobuf/testdata/golden_message \ + google/protobuf/testdata/golden_message_oneof_implemented \ google/protobuf/testdata/golden_packed_fields_message \ + google/protobuf/testdata/bad_utf8_string \ google/protobuf/testdata/text_format_unittest_data.txt \ - google/protobuf/testdata/text_format_unittest_extensions_data.txt \ + google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt \ + google/protobuf/testdata/text_format_unittest_data_pointy.txt \ + google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt \ + google/protobuf/testdata/text_format_unittest_extensions_data.txt \ + google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt \ google/protobuf/package_info.h \ google/protobuf/io/package_info.h \ google/protobuf/compiler/package_info.h \ @@ -257,7 +302,9 @@ protoc_lite_outputs = \ google/protobuf/unittest_lite.pb.cc \ google/protobuf/unittest_lite.pb.h \ google/protobuf/unittest_import_lite.pb.cc \ - google/protobuf/unittest_import_lite.pb.h + google/protobuf/unittest_import_lite.pb.h \ + google/protobuf/unittest_import_public_lite.pb.cc \ + google/protobuf/unittest_import_public_lite.pb.h protoc_outputs = \ $(protoc_lite_outputs) \ @@ -267,6 +314,8 @@ protoc_outputs = \ google/protobuf/unittest_empty.pb.h \ google/protobuf/unittest_import.pb.cc \ google/protobuf/unittest_import.pb.h \ + google/protobuf/unittest_import_public.pb.cc \ + google/protobuf/unittest_import_public.pb.h \ google/protobuf/unittest_mset.pb.cc \ google/protobuf/unittest_mset.pb.h \ google/protobuf/unittest_optimize_for.pb.cc \ @@ -327,6 +376,9 @@ protobuf_test_SOURCES = \ google/protobuf/stubs/once_unittest.cc \ google/protobuf/stubs/strutil_unittest.cc \ google/protobuf/stubs/structurally_valid_unittest.cc \ + google/protobuf/stubs/stringprintf_unittest.cc \ + google/protobuf/stubs/template_util_unittest.cc \ + google/protobuf/stubs/type_traits_unittest.cc \ google/protobuf/descriptor_database_unittest.cc \ google/protobuf/descriptor_unittest.cc \ google/protobuf/dynamic_message_unittest.cc \ @@ -335,6 +387,7 @@ protobuf_test_SOURCES = \ google/protobuf/message_unittest.cc \ google/protobuf/reflection_ops_unittest.cc \ google/protobuf/repeated_field_unittest.cc \ + google/protobuf/repeated_field_reflection_unittest.cc \ google/protobuf/text_format_unittest.cc \ google/protobuf/unknown_field_set_unittest.cc \ google/protobuf/wire_format_unittest.cc \ @@ -348,16 +401,19 @@ protobuf_test_SOURCES = \ google/protobuf/compiler/mock_code_generator.h \ google/protobuf/compiler/parser_unittest.cc \ google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc \ + google/protobuf/compiler/cpp/cpp_unittest.h \ google/protobuf/compiler/cpp/cpp_unittest.cc \ google/protobuf/compiler/cpp/cpp_plugin_unittest.cc \ google/protobuf/compiler/java/java_plugin_unittest.cc \ + google/protobuf/compiler/java/java_doc_comment_unittest.cc \ google/protobuf/compiler/python/python_plugin_unittest.cc \ $(COMMON_TEST_SOURCES) nodist_protobuf_test_SOURCES = $(protoc_outputs) # Run cpp_unittest again with PROTOBUF_TEST_NO_DESCRIPTORS defined. protobuf_lazy_descriptor_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \ - $(top_builddir)/gtest/lib/libgtest.la \ + libprotoc.la \ + $(top_builddir)/gtest/lib/libgtest.la \ $(top_builddir)/gtest/lib/libgtest_main.la protobuf_lazy_descriptor_test_CPPFLAGS = -I$(top_srcdir)/gtest/include \ -I$(top_builddir)/gtest/include \ diff --git a/src/Makefile.in b/src/Makefile.in index 3896427..7f15f5e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -96,90 +96,162 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libprotobuf_lite_la_DEPENDENCIES = $(am__DEPENDENCIES_1) -am_libprotobuf_lite_la_OBJECTS = common.lo once.lo hash.lo \ - extension_set.lo generated_message_util.lo message_lite.lo \ - repeated_field.lo wire_format_lite.lo coded_stream.lo \ - zero_copy_stream.lo zero_copy_stream_impl_lite.lo +am__dirstamp = $(am__leading_dot)dirstamp +am_libprotobuf_lite_la_OBJECTS = \ + google/protobuf/stubs/atomicops_internals_x86_gcc.lo \ + google/protobuf/stubs/atomicops_internals_x86_msvc.lo \ + google/protobuf/stubs/common.lo google/protobuf/stubs/once.lo \ + google/protobuf/stubs/stringprintf.lo \ + google/protobuf/extension_set.lo \ + google/protobuf/generated_message_util.lo \ + google/protobuf/message_lite.lo \ + google/protobuf/repeated_field.lo \ + google/protobuf/wire_format_lite.lo \ + google/protobuf/io/coded_stream.lo \ + google/protobuf/io/zero_copy_stream.lo \ + google/protobuf/io/zero_copy_stream_impl_lite.lo libprotobuf_lite_la_OBJECTS = $(am_libprotobuf_lite_la_OBJECTS) libprotobuf_lite_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(libprotobuf_lite_la_LDFLAGS) $(LDFLAGS) -o $@ libprotobuf_la_DEPENDENCIES = $(am__DEPENDENCIES_1) -am__objects_1 = common.lo once.lo hash.lo extension_set.lo \ - generated_message_util.lo message_lite.lo repeated_field.lo \ - wire_format_lite.lo coded_stream.lo zero_copy_stream.lo \ - zero_copy_stream_impl_lite.lo -am_libprotobuf_la_OBJECTS = $(am__objects_1) strutil.lo substitute.lo \ - structurally_valid.lo descriptor.lo descriptor.pb.lo \ - descriptor_database.lo dynamic_message.lo \ - extension_set_heavy.lo generated_message_reflection.lo \ - message.lo reflection_ops.lo service.lo text_format.lo \ - unknown_field_set.lo wire_format.lo gzip_stream.lo printer.lo \ - tokenizer.lo zero_copy_stream_impl.lo importer.lo parser.lo +am__objects_1 = google/protobuf/stubs/atomicops_internals_x86_gcc.lo \ + google/protobuf/stubs/atomicops_internals_x86_msvc.lo \ + google/protobuf/stubs/common.lo google/protobuf/stubs/once.lo \ + google/protobuf/stubs/stringprintf.lo \ + google/protobuf/extension_set.lo \ + google/protobuf/generated_message_util.lo \ + google/protobuf/message_lite.lo \ + google/protobuf/repeated_field.lo \ + google/protobuf/wire_format_lite.lo \ + google/protobuf/io/coded_stream.lo \ + google/protobuf/io/zero_copy_stream.lo \ + google/protobuf/io/zero_copy_stream_impl_lite.lo +am_libprotobuf_la_OBJECTS = $(am__objects_1) \ + google/protobuf/stubs/strutil.lo \ + google/protobuf/stubs/substitute.lo \ + google/protobuf/stubs/structurally_valid.lo \ + google/protobuf/descriptor.lo google/protobuf/descriptor.pb.lo \ + google/protobuf/descriptor_database.lo \ + google/protobuf/dynamic_message.lo \ + google/protobuf/extension_set_heavy.lo \ + google/protobuf/generated_message_reflection.lo \ + google/protobuf/message.lo google/protobuf/reflection_ops.lo \ + google/protobuf/service.lo google/protobuf/text_format.lo \ + google/protobuf/unknown_field_set.lo \ + google/protobuf/wire_format.lo \ + google/protobuf/io/gzip_stream.lo \ + google/protobuf/io/printer.lo google/protobuf/io/strtod.lo \ + google/protobuf/io/tokenizer.lo \ + google/protobuf/io/zero_copy_stream_impl.lo \ + google/protobuf/compiler/importer.lo \ + google/protobuf/compiler/parser.lo libprotobuf_la_OBJECTS = $(am_libprotobuf_la_OBJECTS) libprotobuf_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(libprotobuf_la_LDFLAGS) $(LDFLAGS) -o $@ libprotoc_la_DEPENDENCIES = $(am__DEPENDENCIES_1) libprotobuf.la -am_libprotoc_la_OBJECTS = code_generator.lo command_line_interface.lo \ - plugin.lo plugin.pb.lo subprocess.lo zip_writer.lo cpp_enum.lo \ - cpp_enum_field.lo cpp_extension.lo cpp_field.lo cpp_file.lo \ - cpp_generator.lo cpp_helpers.lo cpp_message.lo \ - cpp_message_field.lo cpp_primitive_field.lo cpp_service.lo \ - cpp_string_field.lo java_enum.lo java_enum_field.lo \ - java_extension.lo java_field.lo java_file.lo java_generator.lo \ - java_helpers.lo java_message.lo java_message_field.lo \ - java_primitive_field.lo java_service.lo javamicro_enum.lo \ - javamicro_enum_field.lo javamicro_field.lo javamicro_file.lo \ - javamicro_generator.lo javamicro_helpers.lo \ - javamicro_message.lo javamicro_message_field.lo \ - javamicro_primitive_field.lo javanano_enum.lo \ - javanano_enum_field.lo javanano_extension.lo javanano_field.lo \ - javanano_file.lo javanano_generator.lo javanano_helpers.lo \ - javanano_message.lo javanano_message_field.lo \ - javanano_primitive_field.lo python_generator.lo +am_libprotoc_la_OBJECTS = google/protobuf/compiler/code_generator.lo \ + google/protobuf/compiler/command_line_interface.lo \ + google/protobuf/compiler/plugin.lo \ + google/protobuf/compiler/plugin.pb.lo \ + google/protobuf/compiler/subprocess.lo \ + google/protobuf/compiler/zip_writer.lo \ + google/protobuf/compiler/cpp/cpp_enum.lo \ + google/protobuf/compiler/cpp/cpp_enum_field.lo \ + google/protobuf/compiler/cpp/cpp_extension.lo \ + google/protobuf/compiler/cpp/cpp_field.lo \ + google/protobuf/compiler/cpp/cpp_file.lo \ + google/protobuf/compiler/cpp/cpp_generator.lo \ + google/protobuf/compiler/cpp/cpp_helpers.lo \ + google/protobuf/compiler/cpp/cpp_message.lo \ + google/protobuf/compiler/cpp/cpp_message_field.lo \ + google/protobuf/compiler/cpp/cpp_primitive_field.lo \ + google/protobuf/compiler/cpp/cpp_service.lo \ + google/protobuf/compiler/cpp/cpp_string_field.lo \ + google/protobuf/compiler/java/java_context.lo \ + google/protobuf/compiler/java/java_enum.lo \ + google/protobuf/compiler/java/java_enum_field.lo \ + google/protobuf/compiler/java/java_extension.lo \ + google/protobuf/compiler/java/java_field.lo \ + google/protobuf/compiler/java/java_file.lo \ + google/protobuf/compiler/java/java_generator.lo \ + google/protobuf/compiler/java/java_generator_factory.lo \ + google/protobuf/compiler/java/java_helpers.lo \ + google/protobuf/compiler/java/java_lazy_message_field.lo \ + google/protobuf/compiler/java/java_message.lo \ + google/protobuf/compiler/java/java_message_field.lo \ + google/protobuf/compiler/java/java_name_resolver.lo \ + google/protobuf/compiler/java/java_primitive_field.lo \ + google/protobuf/compiler/java/java_shared_code_generator.lo \ + google/protobuf/compiler/java/java_service.lo \ + google/protobuf/compiler/java/java_string_field.lo \ + google/protobuf/compiler/java/java_doc_comment.lo \ + google/protobuf/compiler/javamicro/javamicro_enum.lo \ + google/protobuf/compiler/javamicro/javamicro_enum_field.lo \ + google/protobuf/compiler/javamicro/javamicro_field.lo \ + google/protobuf/compiler/javamicro/javamicro_file.lo \ + google/protobuf/compiler/javamicro/javamicro_generator.lo \ + google/protobuf/compiler/javamicro/javamicro_helpers.lo \ + google/protobuf/compiler/javamicro/javamicro_message.lo \ + google/protobuf/compiler/javamicro/javamicro_message_field.lo \ + google/protobuf/compiler/javamicro/javamicro_primitive_field.lo \ + google/protobuf/compiler/javanano/javanano_enum.lo \ + google/protobuf/compiler/javanano/javanano_enum_field.lo \ + google/protobuf/compiler/javanano/javanano_extension.lo \ + google/protobuf/compiler/javanano/javanano_field.lo \ + google/protobuf/compiler/javanano/javanano_file.lo \ + google/protobuf/compiler/javanano/javanano_generator.lo \ + google/protobuf/compiler/javanano/javanano_helpers.lo \ + google/protobuf/compiler/javanano/javanano_message.lo \ + google/protobuf/compiler/javanano/javanano_message_field.lo \ + google/protobuf/compiler/javanano/javanano_primitive_field.lo \ + google/protobuf/compiler/python/python_generator.lo libprotoc_la_OBJECTS = $(am_libprotoc_la_OBJECTS) libprotoc_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(libprotoc_la_LDFLAGS) $(LDFLAGS) -o $@ @HAVE_ZLIB_TRUE@am__EXEEXT_1 = zcgzip$(EXEEXT) zcgunzip$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) -am__objects_2 = protobuf_lazy_descriptor_test-test_util.$(OBJEXT) \ - protobuf_lazy_descriptor_test-googletest.$(OBJEXT) \ - protobuf_lazy_descriptor_test-file.$(OBJEXT) -am_protobuf_lazy_descriptor_test_OBJECTS = \ - protobuf_lazy_descriptor_test-cpp_unittest.$(OBJEXT) \ +am__objects_2 = google/protobuf/protobuf_lazy_descriptor_test-test_util.$(OBJEXT) \ + google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.$(OBJEXT) \ + google/protobuf/testing/protobuf_lazy_descriptor_test-file.$(OBJEXT) +am_protobuf_lazy_descriptor_test_OBJECTS = google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.$(OBJEXT) \ $(am__objects_2) -am__objects_3 = \ - protobuf_lazy_descriptor_test-unittest_lite.pb.$(OBJEXT) \ - protobuf_lazy_descriptor_test-unittest_import_lite.pb.$(OBJEXT) +am__objects_3 = google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.$(OBJEXT) \ + google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.$(OBJEXT) \ + google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.$(OBJEXT) am__objects_4 = $(am__objects_3) \ - protobuf_lazy_descriptor_test-unittest.pb.$(OBJEXT) \ - protobuf_lazy_descriptor_test-unittest_empty.pb.$(OBJEXT) \ - protobuf_lazy_descriptor_test-unittest_import.pb.$(OBJEXT) \ - protobuf_lazy_descriptor_test-unittest_mset.pb.$(OBJEXT) \ - protobuf_lazy_descriptor_test-unittest_optimize_for.pb.$(OBJEXT) \ - protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.$(OBJEXT) \ - protobuf_lazy_descriptor_test-unittest_custom_options.pb.$(OBJEXT) \ - protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.$(OBJEXT) \ - protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.$(OBJEXT) \ - protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.$(OBJEXT) + google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.$(OBJEXT) \ + google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.$(OBJEXT) \ + google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.$(OBJEXT) \ + google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.$(OBJEXT) \ + google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.$(OBJEXT) \ + google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.$(OBJEXT) \ + google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.$(OBJEXT) \ + google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.$(OBJEXT) \ + google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.$(OBJEXT) \ + google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.$(OBJEXT) \ + google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.$(OBJEXT) nodist_protobuf_lazy_descriptor_test_OBJECTS = $(am__objects_4) protobuf_lazy_descriptor_test_OBJECTS = \ $(am_protobuf_lazy_descriptor_test_OBJECTS) \ $(nodist_protobuf_lazy_descriptor_test_OBJECTS) protobuf_lazy_descriptor_test_DEPENDENCIES = $(am__DEPENDENCIES_1) \ - libprotobuf.la $(top_builddir)/gtest/lib/libgtest.la \ + libprotobuf.la libprotoc.la \ + $(top_builddir)/gtest/lib/libgtest.la \ $(top_builddir)/gtest/lib/libgtest_main.la protobuf_lazy_descriptor_test_LINK = $(LIBTOOL) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_protobuf_lite_test_OBJECTS = \ - protobuf_lite_test-lite_unittest.$(OBJEXT) \ - protobuf_lite_test-test_util_lite.$(OBJEXT) -am__objects_5 = protobuf_lite_test-unittest_lite.pb.$(OBJEXT) \ - protobuf_lite_test-unittest_import_lite.pb.$(OBJEXT) + google/protobuf/protobuf_lite_test-lite_unittest.$(OBJEXT) \ + google/protobuf/protobuf_lite_test-test_util_lite.$(OBJEXT) +am__objects_5 = \ + google/protobuf/protobuf_lite_test-unittest_lite.pb.$(OBJEXT) \ + google/protobuf/protobuf_lite_test-unittest_import_lite.pb.$(OBJEXT) \ + google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.$(OBJEXT) nodist_protobuf_lite_test_OBJECTS = $(am__objects_5) protobuf_lite_test_OBJECTS = $(am_protobuf_lite_test_OBJECTS) \ $(nodist_protobuf_lite_test_OBJECTS) @@ -189,50 +261,60 @@ protobuf_lite_test_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -am__objects_6 = protobuf_test-test_util.$(OBJEXT) \ - protobuf_test-googletest.$(OBJEXT) \ - protobuf_test-file.$(OBJEXT) -am_protobuf_test_OBJECTS = protobuf_test-common_unittest.$(OBJEXT) \ - protobuf_test-once_unittest.$(OBJEXT) \ - protobuf_test-strutil_unittest.$(OBJEXT) \ - protobuf_test-structurally_valid_unittest.$(OBJEXT) \ - protobuf_test-descriptor_database_unittest.$(OBJEXT) \ - protobuf_test-descriptor_unittest.$(OBJEXT) \ - protobuf_test-dynamic_message_unittest.$(OBJEXT) \ - protobuf_test-extension_set_unittest.$(OBJEXT) \ - protobuf_test-generated_message_reflection_unittest.$(OBJEXT) \ - protobuf_test-message_unittest.$(OBJEXT) \ - protobuf_test-reflection_ops_unittest.$(OBJEXT) \ - protobuf_test-repeated_field_unittest.$(OBJEXT) \ - protobuf_test-text_format_unittest.$(OBJEXT) \ - protobuf_test-unknown_field_set_unittest.$(OBJEXT) \ - protobuf_test-wire_format_unittest.$(OBJEXT) \ - protobuf_test-coded_stream_unittest.$(OBJEXT) \ - protobuf_test-printer_unittest.$(OBJEXT) \ - protobuf_test-tokenizer_unittest.$(OBJEXT) \ - protobuf_test-zero_copy_stream_unittest.$(OBJEXT) \ - protobuf_test-command_line_interface_unittest.$(OBJEXT) \ - protobuf_test-importer_unittest.$(OBJEXT) \ - protobuf_test-mock_code_generator.$(OBJEXT) \ - protobuf_test-parser_unittest.$(OBJEXT) \ - protobuf_test-cpp_bootstrap_unittest.$(OBJEXT) \ - protobuf_test-cpp_unittest.$(OBJEXT) \ - protobuf_test-cpp_plugin_unittest.$(OBJEXT) \ - protobuf_test-java_plugin_unittest.$(OBJEXT) \ - protobuf_test-python_plugin_unittest.$(OBJEXT) \ +am__objects_6 = google/protobuf/protobuf_test-test_util.$(OBJEXT) \ + google/protobuf/testing/protobuf_test-googletest.$(OBJEXT) \ + google/protobuf/testing/protobuf_test-file.$(OBJEXT) +am_protobuf_test_OBJECTS = \ + google/protobuf/stubs/protobuf_test-common_unittest.$(OBJEXT) \ + google/protobuf/stubs/protobuf_test-once_unittest.$(OBJEXT) \ + google/protobuf/stubs/protobuf_test-strutil_unittest.$(OBJEXT) \ + google/protobuf/stubs/protobuf_test-structurally_valid_unittest.$(OBJEXT) \ + google/protobuf/stubs/protobuf_test-stringprintf_unittest.$(OBJEXT) \ + google/protobuf/stubs/protobuf_test-template_util_unittest.$(OBJEXT) \ + google/protobuf/stubs/protobuf_test-type_traits_unittest.$(OBJEXT) \ + google/protobuf/protobuf_test-descriptor_database_unittest.$(OBJEXT) \ + google/protobuf/protobuf_test-descriptor_unittest.$(OBJEXT) \ + google/protobuf/protobuf_test-dynamic_message_unittest.$(OBJEXT) \ + google/protobuf/protobuf_test-extension_set_unittest.$(OBJEXT) \ + google/protobuf/protobuf_test-generated_message_reflection_unittest.$(OBJEXT) \ + google/protobuf/protobuf_test-message_unittest.$(OBJEXT) \ + google/protobuf/protobuf_test-reflection_ops_unittest.$(OBJEXT) \ + google/protobuf/protobuf_test-repeated_field_unittest.$(OBJEXT) \ + google/protobuf/protobuf_test-repeated_field_reflection_unittest.$(OBJEXT) \ + google/protobuf/protobuf_test-text_format_unittest.$(OBJEXT) \ + google/protobuf/protobuf_test-unknown_field_set_unittest.$(OBJEXT) \ + google/protobuf/protobuf_test-wire_format_unittest.$(OBJEXT) \ + google/protobuf/io/protobuf_test-coded_stream_unittest.$(OBJEXT) \ + google/protobuf/io/protobuf_test-printer_unittest.$(OBJEXT) \ + google/protobuf/io/protobuf_test-tokenizer_unittest.$(OBJEXT) \ + google/protobuf/io/protobuf_test-zero_copy_stream_unittest.$(OBJEXT) \ + google/protobuf/compiler/protobuf_test-command_line_interface_unittest.$(OBJEXT) \ + google/protobuf/compiler/protobuf_test-importer_unittest.$(OBJEXT) \ + google/protobuf/compiler/protobuf_test-mock_code_generator.$(OBJEXT) \ + google/protobuf/compiler/protobuf_test-parser_unittest.$(OBJEXT) \ + google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.$(OBJEXT) \ + google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.$(OBJEXT) \ + google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.$(OBJEXT) \ + google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.$(OBJEXT) \ + google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.$(OBJEXT) \ + google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.$(OBJEXT) \ $(am__objects_6) -am__objects_7 = protobuf_test-unittest_lite.pb.$(OBJEXT) \ - protobuf_test-unittest_import_lite.pb.$(OBJEXT) -am__objects_8 = $(am__objects_7) protobuf_test-unittest.pb.$(OBJEXT) \ - protobuf_test-unittest_empty.pb.$(OBJEXT) \ - protobuf_test-unittest_import.pb.$(OBJEXT) \ - protobuf_test-unittest_mset.pb.$(OBJEXT) \ - protobuf_test-unittest_optimize_for.pb.$(OBJEXT) \ - protobuf_test-unittest_embed_optimize_for.pb.$(OBJEXT) \ - protobuf_test-unittest_custom_options.pb.$(OBJEXT) \ - protobuf_test-unittest_lite_imports_nonlite.pb.$(OBJEXT) \ - protobuf_test-unittest_no_generic_services.pb.$(OBJEXT) \ - protobuf_test-cpp_test_bad_identifiers.pb.$(OBJEXT) +am__objects_7 = \ + google/protobuf/protobuf_test-unittest_lite.pb.$(OBJEXT) \ + google/protobuf/protobuf_test-unittest_import_lite.pb.$(OBJEXT) \ + google/protobuf/protobuf_test-unittest_import_public_lite.pb.$(OBJEXT) +am__objects_8 = $(am__objects_7) \ + google/protobuf/protobuf_test-unittest.pb.$(OBJEXT) \ + google/protobuf/protobuf_test-unittest_empty.pb.$(OBJEXT) \ + google/protobuf/protobuf_test-unittest_import.pb.$(OBJEXT) \ + google/protobuf/protobuf_test-unittest_import_public.pb.$(OBJEXT) \ + google/protobuf/protobuf_test-unittest_mset.pb.$(OBJEXT) \ + google/protobuf/protobuf_test-unittest_optimize_for.pb.$(OBJEXT) \ + google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.$(OBJEXT) \ + google/protobuf/protobuf_test-unittest_custom_options.pb.$(OBJEXT) \ + google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.$(OBJEXT) \ + google/protobuf/protobuf_test-unittest_no_generic_services.pb.$(OBJEXT) \ + google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.$(OBJEXT) nodist_protobuf_test_OBJECTS = $(am__objects_8) protobuf_test_OBJECTS = $(am_protobuf_test_OBJECTS) \ $(nodist_protobuf_test_OBJECTS) @@ -242,22 +324,25 @@ protobuf_test_DEPENDENCIES = $(am__DEPENDENCIES_1) libprotobuf.la \ protobuf_test_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(protobuf_test_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -am_protoc_OBJECTS = main.$(OBJEXT) +am_protoc_OBJECTS = google/protobuf/compiler/main.$(OBJEXT) protoc_OBJECTS = $(am_protoc_OBJECTS) protoc_DEPENDENCIES = $(am__DEPENDENCIES_1) libprotobuf.la \ libprotoc.la -am_test_plugin_OBJECTS = test_plugin-mock_code_generator.$(OBJEXT) \ - test_plugin-file.$(OBJEXT) test_plugin-test_plugin.$(OBJEXT) +am_test_plugin_OBJECTS = google/protobuf/compiler/test_plugin-mock_code_generator.$(OBJEXT) \ + google/protobuf/testing/test_plugin-file.$(OBJEXT) \ + google/protobuf/compiler/test_plugin-test_plugin.$(OBJEXT) test_plugin_OBJECTS = $(am_test_plugin_OBJECTS) test_plugin_DEPENDENCIES = $(am__DEPENDENCIES_1) libprotobuf.la \ libprotoc.la $(top_builddir)/gtest/lib/libgtest.la am__zcgunzip_SOURCES_DIST = google/protobuf/testing/zcgunzip.cc -@HAVE_ZLIB_TRUE@am_zcgunzip_OBJECTS = zcgunzip.$(OBJEXT) +@HAVE_ZLIB_TRUE@am_zcgunzip_OBJECTS = \ +@HAVE_ZLIB_TRUE@ google/protobuf/testing/zcgunzip.$(OBJEXT) zcgunzip_OBJECTS = $(am_zcgunzip_OBJECTS) @HAVE_ZLIB_TRUE@zcgunzip_DEPENDENCIES = $(am__DEPENDENCIES_1) \ @HAVE_ZLIB_TRUE@ libprotobuf.la am__zcgzip_SOURCES_DIST = google/protobuf/testing/zcgzip.cc -@HAVE_ZLIB_TRUE@am_zcgzip_OBJECTS = zcgzip.$(OBJEXT) +@HAVE_ZLIB_TRUE@am_zcgzip_OBJECTS = \ +@HAVE_ZLIB_TRUE@ google/protobuf/testing/zcgzip.$(OBJEXT) zcgzip_OBJECTS = $(am_zcgzip_OBJECTS) @HAVE_ZLIB_TRUE@zcgzip_DEPENDENCIES = $(am__DEPENDENCIES_1) \ @HAVE_ZLIB_TRUE@ libprotobuf.la @@ -298,12 +383,28 @@ DIST_SOURCES = $(libprotobuf_lite_la_SOURCES) \ $(protoc_SOURCES) $(test_plugin_SOURCES) \ $(am__zcgunzip_SOURCES_DIST) $(am__zcgzip_SOURCES_DIST) DATA = $(nobase_dist_proto_DATA) -am__nobase_include_HEADERS_DIST = google/protobuf/stubs/common.h \ - google/protobuf/stubs/once.h google/protobuf/descriptor.h \ - google/protobuf/descriptor.pb.h \ +am__nobase_include_HEADERS_DIST = google/protobuf/stubs/atomicops.h \ + google/protobuf/stubs/atomicops_internals_arm_gcc.h \ + google/protobuf/stubs/atomicops_internals_arm64_gcc.h \ + google/protobuf/stubs/atomicops_internals_arm_qnx.h \ + google/protobuf/stubs/atomicops_internals_atomicword_compat.h \ + google/protobuf/stubs/atomicops_internals_generic_gcc.h \ + google/protobuf/stubs/atomicops_internals_macosx.h \ + google/protobuf/stubs/atomicops_internals_mips_gcc.h \ + google/protobuf/stubs/atomicops_internals_pnacl.h \ + google/protobuf/stubs/atomicops_internals_tsan.h \ + google/protobuf/stubs/atomicops_internals_x86_gcc.h \ + google/protobuf/stubs/atomicops_internals_x86_msvc.h \ + google/protobuf/stubs/common.h \ + google/protobuf/stubs/platform_macros.h \ + google/protobuf/stubs/once.h google/protobuf/stubs/stl_util.h \ + google/protobuf/stubs/template_util.h \ + google/protobuf/stubs/type_traits.h \ + google/protobuf/descriptor.h google/protobuf/descriptor.pb.h \ google/protobuf/descriptor_database.h \ google/protobuf/dynamic_message.h \ google/protobuf/extension_set.h \ + google/protobuf/generated_enum_reflection.h \ google/protobuf/generated_message_util.h \ google/protobuf/generated_message_reflection.h \ google/protobuf/message.h google/protobuf/message_lite.h \ @@ -316,7 +417,7 @@ am__nobase_include_HEADERS_DIST = google/protobuf/stubs/common.h \ google/protobuf/wire_format_lite_inl.h \ google/protobuf/io/coded_stream.h \ google/protobuf/io/gzip_stream.h google/protobuf/io/printer.h \ - google/protobuf/io/tokenizer.h \ + google/protobuf/io/strtod.h google/protobuf/io/tokenizer.h \ google/protobuf/io/zero_copy_stream.h \ google/protobuf/io/zero_copy_stream_impl.h \ google/protobuf/io/zero_copy_stream_impl_lite.h \ @@ -357,6 +458,7 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -380,10 +482,13 @@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ @@ -411,6 +516,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ @@ -445,7 +551,6 @@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ @@ -492,54 +597,75 @@ MAINTAINERCLEANFILES = \ Makefile.in nobase_include_HEADERS = \ - google/protobuf/stubs/common.h \ - google/protobuf/stubs/once.h \ - google/protobuf/descriptor.h \ - google/protobuf/descriptor.pb.h \ - google/protobuf/descriptor_database.h \ - google/protobuf/dynamic_message.h \ - google/protobuf/extension_set.h \ - google/protobuf/generated_message_util.h \ - google/protobuf/generated_message_reflection.h \ - google/protobuf/message.h \ - google/protobuf/message_lite.h \ - google/protobuf/reflection_ops.h \ - google/protobuf/repeated_field.h \ - google/protobuf/service.h \ - google/protobuf/text_format.h \ - google/protobuf/unknown_field_set.h \ - google/protobuf/wire_format.h \ - google/protobuf/wire_format_lite.h \ - google/protobuf/wire_format_lite_inl.h \ - google/protobuf/io/coded_stream.h \ - $(GZHEADERS) \ - google/protobuf/io/printer.h \ - google/protobuf/io/tokenizer.h \ - google/protobuf/io/zero_copy_stream.h \ - google/protobuf/io/zero_copy_stream_impl.h \ - google/protobuf/io/zero_copy_stream_impl_lite.h \ - google/protobuf/compiler/code_generator.h \ - google/protobuf/compiler/command_line_interface.h \ - google/protobuf/compiler/importer.h \ - google/protobuf/compiler/parser.h \ - google/protobuf/compiler/plugin.h \ - google/protobuf/compiler/plugin.pb.h \ - google/protobuf/compiler/cpp/cpp_generator.h \ - google/protobuf/compiler/java/java_generator.h \ - google/protobuf/compiler/javamicro/javamicro_generator.h \ - google/protobuf/compiler/javanano/javanano_generator.h \ + google/protobuf/stubs/atomicops.h \ + google/protobuf/stubs/atomicops_internals_arm_gcc.h \ + google/protobuf/stubs/atomicops_internals_arm64_gcc.h \ + google/protobuf/stubs/atomicops_internals_arm_qnx.h \ + google/protobuf/stubs/atomicops_internals_atomicword_compat.h \ + google/protobuf/stubs/atomicops_internals_generic_gcc.h \ + google/protobuf/stubs/atomicops_internals_macosx.h \ + google/protobuf/stubs/atomicops_internals_mips_gcc.h \ + google/protobuf/stubs/atomicops_internals_pnacl.h \ + google/protobuf/stubs/atomicops_internals_tsan.h \ + google/protobuf/stubs/atomicops_internals_x86_gcc.h \ + google/protobuf/stubs/atomicops_internals_x86_msvc.h \ + google/protobuf/stubs/common.h \ + google/protobuf/stubs/platform_macros.h \ + google/protobuf/stubs/once.h \ + google/protobuf/stubs/stl_util.h \ + google/protobuf/stubs/template_util.h \ + google/protobuf/stubs/type_traits.h \ + google/protobuf/descriptor.h \ + google/protobuf/descriptor.pb.h \ + google/protobuf/descriptor_database.h \ + google/protobuf/dynamic_message.h \ + google/protobuf/extension_set.h \ + google/protobuf/generated_enum_reflection.h \ + google/protobuf/generated_message_util.h \ + google/protobuf/generated_message_reflection.h \ + google/protobuf/message.h \ + google/protobuf/message_lite.h \ + google/protobuf/reflection_ops.h \ + google/protobuf/repeated_field.h \ + google/protobuf/service.h \ + google/protobuf/text_format.h \ + google/protobuf/unknown_field_set.h \ + google/protobuf/wire_format.h \ + google/protobuf/wire_format_lite.h \ + google/protobuf/wire_format_lite_inl.h \ + google/protobuf/io/coded_stream.h \ + $(GZHEADERS) \ + google/protobuf/io/printer.h \ + google/protobuf/io/strtod.h \ + google/protobuf/io/tokenizer.h \ + google/protobuf/io/zero_copy_stream.h \ + google/protobuf/io/zero_copy_stream_impl.h \ + google/protobuf/io/zero_copy_stream_impl_lite.h \ + google/protobuf/compiler/code_generator.h \ + google/protobuf/compiler/command_line_interface.h \ + google/protobuf/compiler/importer.h \ + google/protobuf/compiler/parser.h \ + google/protobuf/compiler/plugin.h \ + google/protobuf/compiler/plugin.pb.h \ + google/protobuf/compiler/cpp/cpp_generator.h \ + google/protobuf/compiler/java/java_generator.h \ + google/protobuf/compiler/javamicro/javamicro_generator.h \ + google/protobuf/compiler/javanano/javanano_generator.h \ google/protobuf/compiler/python/python_generator.h lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS) -libprotobuf_lite_la_LDFLAGS = -version-info 6:0:0 -export-dynamic -no-undefined +libprotobuf_lite_la_LDFLAGS = -version-info 9:0:0 -export-dynamic -no-undefined libprotobuf_lite_la_SOURCES = \ + google/protobuf/stubs/atomicops_internals_x86_gcc.cc \ + google/protobuf/stubs/atomicops_internals_x86_msvc.cc \ google/protobuf/stubs/common.cc \ google/protobuf/stubs/once.cc \ - google/protobuf/stubs/hash.cc \ google/protobuf/stubs/hash.h \ - google/protobuf/stubs/map-util.h \ - google/protobuf/stubs/stl_util-inl.h \ + google/protobuf/stubs/map_util.h \ + google/protobuf/stubs/shared_ptr.h \ + google/protobuf/stubs/stringprintf.cc \ + google/protobuf/stubs/stringprintf.h \ google/protobuf/extension_set.cc \ google/protobuf/generated_message_util.cc \ google/protobuf/message_lite.cc \ @@ -551,7 +677,7 @@ libprotobuf_lite_la_SOURCES = \ google/protobuf/io/zero_copy_stream_impl_lite.cc libprotobuf_la_LIBADD = $(PTHREAD_LIBS) -libprotobuf_la_LDFLAGS = -version-info 6:0:0 -export-dynamic -no-undefined +libprotobuf_la_LDFLAGS = -version-info 9:0:0 -export-dynamic -no-undefined libprotobuf_la_SOURCES = \ $(libprotobuf_lite_la_SOURCES) \ google/protobuf/stubs/strutil.cc \ @@ -573,13 +699,14 @@ libprotobuf_la_SOURCES = \ google/protobuf/wire_format.cc \ google/protobuf/io/gzip_stream.cc \ google/protobuf/io/printer.cc \ + google/protobuf/io/strtod.cc \ google/protobuf/io/tokenizer.cc \ google/protobuf/io/zero_copy_stream_impl.cc \ google/protobuf/compiler/importer.cc \ google/protobuf/compiler/parser.cc libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la -libprotoc_la_LDFLAGS = -version-info 6:0:0 -export-dynamic -no-undefined +libprotoc_la_LDFLAGS = -version-info 9:0:0 -export-dynamic -no-undefined libprotoc_la_SOURCES = \ google/protobuf/compiler/code_generator.cc \ google/protobuf/compiler/command_line_interface.cc \ @@ -606,12 +733,15 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/cpp/cpp_message.h \ google/protobuf/compiler/cpp/cpp_message_field.cc \ google/protobuf/compiler/cpp/cpp_message_field.h \ + google/protobuf/compiler/cpp/cpp_options.h \ google/protobuf/compiler/cpp/cpp_primitive_field.cc \ google/protobuf/compiler/cpp/cpp_primitive_field.h \ google/protobuf/compiler/cpp/cpp_service.cc \ google/protobuf/compiler/cpp/cpp_service.h \ google/protobuf/compiler/cpp/cpp_string_field.cc \ google/protobuf/compiler/cpp/cpp_string_field.h \ + google/protobuf/compiler/java/java_context.cc \ + google/protobuf/compiler/java/java_context.h \ google/protobuf/compiler/java/java_enum.cc \ google/protobuf/compiler/java/java_enum.h \ google/protobuf/compiler/java/java_enum_field.cc \ @@ -623,16 +753,28 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/java/java_file.cc \ google/protobuf/compiler/java/java_file.h \ google/protobuf/compiler/java/java_generator.cc \ + google/protobuf/compiler/java/java_generator_factory.cc \ + google/protobuf/compiler/java/java_generator_factory.h \ google/protobuf/compiler/java/java_helpers.cc \ google/protobuf/compiler/java/java_helpers.h \ + google/protobuf/compiler/java/java_lazy_message_field.cc \ + google/protobuf/compiler/java/java_lazy_message_field.h \ google/protobuf/compiler/java/java_message.cc \ google/protobuf/compiler/java/java_message.h \ google/protobuf/compiler/java/java_message_field.cc \ google/protobuf/compiler/java/java_message_field.h \ + google/protobuf/compiler/java/java_name_resolver.cc \ + google/protobuf/compiler/java/java_name_resolver.h \ google/protobuf/compiler/java/java_primitive_field.cc \ google/protobuf/compiler/java/java_primitive_field.h \ + google/protobuf/compiler/java/java_shared_code_generator.cc \ + google/protobuf/compiler/java/java_shared_code_generator.h \ google/protobuf/compiler/java/java_service.cc \ google/protobuf/compiler/java/java_service.h \ + google/protobuf/compiler/java/java_string_field.cc \ + google/protobuf/compiler/java/java_string_field.h \ + google/protobuf/compiler/java/java_doc_comment.cc \ + google/protobuf/compiler/java/java_doc_comment.h \ google/protobuf/compiler/javamicro/javamicro_enum.cc \ google/protobuf/compiler/javamicro/javamicro_enum.h \ google/protobuf/compiler/javamicro/javamicro_enum_field.cc \ @@ -679,12 +821,14 @@ protoc_inputs = \ google/protobuf/unittest.proto \ google/protobuf/unittest_empty.proto \ google/protobuf/unittest_import.proto \ + google/protobuf/unittest_import_public.proto \ google/protobuf/unittest_mset.proto \ google/protobuf/unittest_optimize_for.proto \ google/protobuf/unittest_embed_optimize_for.proto \ google/protobuf/unittest_custom_options.proto \ google/protobuf/unittest_lite.proto \ google/protobuf/unittest_import_lite.proto \ + google/protobuf/unittest_import_public_lite.proto \ google/protobuf/unittest_lite_imports_nonlite.proto \ google/protobuf/unittest_no_generic_services.proto \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto @@ -695,9 +839,15 @@ EXTRA_DIST = \ google/protobuf/io/gzip_stream.h \ google/protobuf/io/gzip_stream_unittest.sh \ google/protobuf/testdata/golden_message \ + google/protobuf/testdata/golden_message_oneof_implemented \ google/protobuf/testdata/golden_packed_fields_message \ + google/protobuf/testdata/bad_utf8_string \ google/protobuf/testdata/text_format_unittest_data.txt \ - google/protobuf/testdata/text_format_unittest_extensions_data.txt \ + google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt \ + google/protobuf/testdata/text_format_unittest_data_pointy.txt \ + google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt \ + google/protobuf/testdata/text_format_unittest_extensions_data.txt \ + google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt \ google/protobuf/package_info.h \ google/protobuf/io/package_info.h \ google/protobuf/compiler/package_info.h \ @@ -708,7 +858,9 @@ protoc_lite_outputs = \ google/protobuf/unittest_lite.pb.cc \ google/protobuf/unittest_lite.pb.h \ google/protobuf/unittest_import_lite.pb.cc \ - google/protobuf/unittest_import_lite.pb.h + google/protobuf/unittest_import_lite.pb.h \ + google/protobuf/unittest_import_public_lite.pb.cc \ + google/protobuf/unittest_import_public_lite.pb.h protoc_outputs = \ $(protoc_lite_outputs) \ @@ -718,6 +870,8 @@ protoc_outputs = \ google/protobuf/unittest_empty.pb.h \ google/protobuf/unittest_import.pb.cc \ google/protobuf/unittest_import.pb.h \ + google/protobuf/unittest_import_public.pb.cc \ + google/protobuf/unittest_import_public.pb.h \ google/protobuf/unittest_mset.pb.cc \ google/protobuf/unittest_mset.pb.h \ google/protobuf/unittest_optimize_for.pb.cc \ @@ -758,6 +912,9 @@ protobuf_test_SOURCES = \ google/protobuf/stubs/once_unittest.cc \ google/protobuf/stubs/strutil_unittest.cc \ google/protobuf/stubs/structurally_valid_unittest.cc \ + google/protobuf/stubs/stringprintf_unittest.cc \ + google/protobuf/stubs/template_util_unittest.cc \ + google/protobuf/stubs/type_traits_unittest.cc \ google/protobuf/descriptor_database_unittest.cc \ google/protobuf/descriptor_unittest.cc \ google/protobuf/dynamic_message_unittest.cc \ @@ -766,6 +923,7 @@ protobuf_test_SOURCES = \ google/protobuf/message_unittest.cc \ google/protobuf/reflection_ops_unittest.cc \ google/protobuf/repeated_field_unittest.cc \ + google/protobuf/repeated_field_reflection_unittest.cc \ google/protobuf/text_format_unittest.cc \ google/protobuf/unknown_field_set_unittest.cc \ google/protobuf/wire_format_unittest.cc \ @@ -779,9 +937,11 @@ protobuf_test_SOURCES = \ google/protobuf/compiler/mock_code_generator.h \ google/protobuf/compiler/parser_unittest.cc \ google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc \ + google/protobuf/compiler/cpp/cpp_unittest.h \ google/protobuf/compiler/cpp/cpp_unittest.cc \ google/protobuf/compiler/cpp/cpp_plugin_unittest.cc \ google/protobuf/compiler/java/java_plugin_unittest.cc \ + google/protobuf/compiler/java/java_doc_comment_unittest.cc \ google/protobuf/compiler/python/python_plugin_unittest.cc \ $(COMMON_TEST_SOURCES) @@ -789,7 +949,8 @@ nodist_protobuf_test_SOURCES = $(protoc_outputs) # Run cpp_unittest again with PROTOBUF_TEST_NO_DESCRIPTORS defined. protobuf_lazy_descriptor_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \ - $(top_builddir)/gtest/lib/libgtest.la \ + libprotoc.la \ + $(top_builddir)/gtest/lib/libgtest.la \ $(top_builddir)/gtest/lib/libgtest_main.la protobuf_lazy_descriptor_test_CPPFLAGS = -I$(top_srcdir)/gtest/include \ @@ -835,7 +996,7 @@ all: $(BUILT_SOURCES) .SUFFIXES: .SUFFIXES: .cc .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -844,9 +1005,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/Makefile + $(AUTOMAKE) --foreign src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -860,9 +1021,9 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(top_srcdir)/configure: $(am__configure_deps) +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @@ -896,10 +1057,319 @@ clean-libLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done +google/protobuf/stubs/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/stubs + @: > google/protobuf/stubs/$(am__dirstamp) +google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/stubs/$(DEPDIR) + @: > google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/atomicops_internals_x86_gcc.lo: \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/atomicops_internals_x86_msvc.lo: \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/common.lo: \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/once.lo: google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/stringprintf.lo: \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/$(am__dirstamp): + @$(MKDIR_P) google/protobuf + @: > google/protobuf/$(am__dirstamp) +google/protobuf/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/$(DEPDIR) + @: > google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/extension_set.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/generated_message_util.lo: \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/message_lite.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/repeated_field.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/wire_format_lite.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/io + @: > google/protobuf/io/$(am__dirstamp) +google/protobuf/io/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/io/$(DEPDIR) + @: > google/protobuf/io/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/coded_stream.lo: \ + google/protobuf/io/$(am__dirstamp) \ + google/protobuf/io/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/zero_copy_stream.lo: \ + google/protobuf/io/$(am__dirstamp) \ + google/protobuf/io/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/zero_copy_stream_impl_lite.lo: \ + google/protobuf/io/$(am__dirstamp) \ + google/protobuf/io/$(DEPDIR)/$(am__dirstamp) libprotobuf-lite.la: $(libprotobuf_lite_la_OBJECTS) $(libprotobuf_lite_la_DEPENDENCIES) $(EXTRA_libprotobuf_lite_la_DEPENDENCIES) $(libprotobuf_lite_la_LINK) -rpath $(libdir) $(libprotobuf_lite_la_OBJECTS) $(libprotobuf_lite_la_LIBADD) $(LIBS) +google/protobuf/stubs/strutil.lo: \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/substitute.lo: \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/structurally_valid.lo: \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/descriptor.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/descriptor.pb.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/descriptor_database.lo: \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/dynamic_message.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/extension_set_heavy.lo: \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/generated_message_reflection.lo: \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/message.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/reflection_ops.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/service.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/text_format.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/unknown_field_set.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/wire_format.lo: google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/gzip_stream.lo: google/protobuf/io/$(am__dirstamp) \ + google/protobuf/io/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/printer.lo: google/protobuf/io/$(am__dirstamp) \ + google/protobuf/io/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/strtod.lo: google/protobuf/io/$(am__dirstamp) \ + google/protobuf/io/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/tokenizer.lo: google/protobuf/io/$(am__dirstamp) \ + google/protobuf/io/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/zero_copy_stream_impl.lo: \ + google/protobuf/io/$(am__dirstamp) \ + google/protobuf/io/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/compiler + @: > google/protobuf/compiler/$(am__dirstamp) +google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/compiler/$(DEPDIR) + @: > google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/importer.lo: \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/parser.lo: \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) libprotobuf.la: $(libprotobuf_la_OBJECTS) $(libprotobuf_la_DEPENDENCIES) $(EXTRA_libprotobuf_la_DEPENDENCIES) $(libprotobuf_la_LINK) -rpath $(libdir) $(libprotobuf_la_OBJECTS) $(libprotobuf_la_LIBADD) $(LIBS) +google/protobuf/compiler/code_generator.lo: \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/command_line_interface.lo: \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/plugin.lo: \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/plugin.pb.lo: \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/subprocess.lo: \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/zip_writer.lo: \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/compiler/cpp + @: > google/protobuf/compiler/cpp/$(am__dirstamp) +google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/compiler/cpp/$(DEPDIR) + @: > google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/cpp_enum.lo: \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/cpp_enum_field.lo: \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/cpp_extension.lo: \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/cpp_field.lo: \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/cpp_file.lo: \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/cpp_generator.lo: \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/cpp_helpers.lo: \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/cpp_message.lo: \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/cpp_message_field.lo: \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/cpp_primitive_field.lo: \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/cpp_service.lo: \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/cpp_string_field.lo: \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/compiler/java + @: > google/protobuf/compiler/java/$(am__dirstamp) +google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/compiler/java/$(DEPDIR) + @: > google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_context.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_enum.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_enum_field.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_extension.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_field.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_file.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_generator.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_generator_factory.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_helpers.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_lazy_message_field.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_message.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_message_field.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_name_resolver.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_primitive_field.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_shared_code_generator.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_service.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_string_field.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/java_doc_comment.lo: \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javamicro/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/compiler/javamicro + @: > google/protobuf/compiler/javamicro/$(am__dirstamp) +google/protobuf/compiler/javamicro/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/compiler/javamicro/$(DEPDIR) + @: > google/protobuf/compiler/javamicro/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javamicro/javamicro_enum.lo: \ + google/protobuf/compiler/javamicro/$(am__dirstamp) \ + google/protobuf/compiler/javamicro/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javamicro/javamicro_enum_field.lo: \ + google/protobuf/compiler/javamicro/$(am__dirstamp) \ + google/protobuf/compiler/javamicro/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javamicro/javamicro_field.lo: \ + google/protobuf/compiler/javamicro/$(am__dirstamp) \ + google/protobuf/compiler/javamicro/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javamicro/javamicro_file.lo: \ + google/protobuf/compiler/javamicro/$(am__dirstamp) \ + google/protobuf/compiler/javamicro/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javamicro/javamicro_generator.lo: \ + google/protobuf/compiler/javamicro/$(am__dirstamp) \ + google/protobuf/compiler/javamicro/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javamicro/javamicro_helpers.lo: \ + google/protobuf/compiler/javamicro/$(am__dirstamp) \ + google/protobuf/compiler/javamicro/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javamicro/javamicro_message.lo: \ + google/protobuf/compiler/javamicro/$(am__dirstamp) \ + google/protobuf/compiler/javamicro/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javamicro/javamicro_message_field.lo: \ + google/protobuf/compiler/javamicro/$(am__dirstamp) \ + google/protobuf/compiler/javamicro/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javamicro/javamicro_primitive_field.lo: \ + google/protobuf/compiler/javamicro/$(am__dirstamp) \ + google/protobuf/compiler/javamicro/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javanano/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/compiler/javanano + @: > google/protobuf/compiler/javanano/$(am__dirstamp) +google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/compiler/javanano/$(DEPDIR) + @: > google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javanano/javanano_enum.lo: \ + google/protobuf/compiler/javanano/$(am__dirstamp) \ + google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javanano/javanano_enum_field.lo: \ + google/protobuf/compiler/javanano/$(am__dirstamp) \ + google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javanano/javanano_extension.lo: \ + google/protobuf/compiler/javanano/$(am__dirstamp) \ + google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javanano/javanano_field.lo: \ + google/protobuf/compiler/javanano/$(am__dirstamp) \ + google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javanano/javanano_file.lo: \ + google/protobuf/compiler/javanano/$(am__dirstamp) \ + google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javanano/javanano_generator.lo: \ + google/protobuf/compiler/javanano/$(am__dirstamp) \ + google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javanano/javanano_helpers.lo: \ + google/protobuf/compiler/javanano/$(am__dirstamp) \ + google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javanano/javanano_message.lo: \ + google/protobuf/compiler/javanano/$(am__dirstamp) \ + google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javanano/javanano_message_field.lo: \ + google/protobuf/compiler/javanano/$(am__dirstamp) \ + google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/javanano/javanano_primitive_field.lo: \ + google/protobuf/compiler/javanano/$(am__dirstamp) \ + google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/python/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/compiler/python + @: > google/protobuf/compiler/python/$(am__dirstamp) +google/protobuf/compiler/python/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/compiler/python/$(DEPDIR) + @: > google/protobuf/compiler/python/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/python/python_generator.lo: \ + google/protobuf/compiler/python/$(am__dirstamp) \ + google/protobuf/compiler/python/$(DEPDIR)/$(am__dirstamp) libprotoc.la: $(libprotoc_la_OBJECTS) $(libprotoc_la_DEPENDENCIES) $(EXTRA_libprotoc_la_DEPENDENCIES) $(libprotoc_la_LINK) -rpath $(libdir) $(libprotoc_la_OBJECTS) $(libprotoc_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @@ -954,1744 +1424,1811 @@ clean-checkPROGRAMS: list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list +google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.$(OBJEXT): \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-test_util.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/testing/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/testing + @: > google/protobuf/testing/$(am__dirstamp) +google/protobuf/testing/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) google/protobuf/testing/$(DEPDIR) + @: > google/protobuf/testing/$(DEPDIR)/$(am__dirstamp) +google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.$(OBJEXT): \ + google/protobuf/testing/$(am__dirstamp) \ + google/protobuf/testing/$(DEPDIR)/$(am__dirstamp) +google/protobuf/testing/protobuf_lazy_descriptor_test-file.$(OBJEXT): \ + google/protobuf/testing/$(am__dirstamp) \ + google/protobuf/testing/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.$(OBJEXT): \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) protobuf-lazy-descriptor-test$(EXEEXT): $(protobuf_lazy_descriptor_test_OBJECTS) $(protobuf_lazy_descriptor_test_DEPENDENCIES) $(EXTRA_protobuf_lazy_descriptor_test_DEPENDENCIES) @rm -f protobuf-lazy-descriptor-test$(EXEEXT) $(protobuf_lazy_descriptor_test_LINK) $(protobuf_lazy_descriptor_test_OBJECTS) $(protobuf_lazy_descriptor_test_LDADD) $(LIBS) +google/protobuf/protobuf_lite_test-lite_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lite_test-test_util_lite.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lite_test-unittest_lite.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lite_test-unittest_import_lite.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) protobuf-lite-test$(EXEEXT): $(protobuf_lite_test_OBJECTS) $(protobuf_lite_test_DEPENDENCIES) $(EXTRA_protobuf_lite_test_DEPENDENCIES) @rm -f protobuf-lite-test$(EXEEXT) $(protobuf_lite_test_LINK) $(protobuf_lite_test_OBJECTS) $(protobuf_lite_test_LDADD) $(LIBS) +google/protobuf/stubs/protobuf_test-common_unittest.$(OBJEXT): \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/protobuf_test-once_unittest.$(OBJEXT): \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/protobuf_test-strutil_unittest.$(OBJEXT): \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/protobuf_test-structurally_valid_unittest.$(OBJEXT): \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/protobuf_test-stringprintf_unittest.$(OBJEXT): \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/protobuf_test-template_util_unittest.$(OBJEXT): \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/stubs/protobuf_test-type_traits_unittest.$(OBJEXT): \ + google/protobuf/stubs/$(am__dirstamp) \ + google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-descriptor_database_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-descriptor_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-dynamic_message_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-extension_set_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-generated_message_reflection_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-message_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-reflection_ops_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-repeated_field_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-repeated_field_reflection_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-text_format_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unknown_field_set_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-wire_format_unittest.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/protobuf_test-coded_stream_unittest.$(OBJEXT): \ + google/protobuf/io/$(am__dirstamp) \ + google/protobuf/io/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/protobuf_test-printer_unittest.$(OBJEXT): \ + google/protobuf/io/$(am__dirstamp) \ + google/protobuf/io/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/protobuf_test-tokenizer_unittest.$(OBJEXT): \ + google/protobuf/io/$(am__dirstamp) \ + google/protobuf/io/$(DEPDIR)/$(am__dirstamp) +google/protobuf/io/protobuf_test-zero_copy_stream_unittest.$(OBJEXT): \ + google/protobuf/io/$(am__dirstamp) \ + google/protobuf/io/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/protobuf_test-command_line_interface_unittest.$(OBJEXT): \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/protobuf_test-importer_unittest.$(OBJEXT): \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/protobuf_test-mock_code_generator.$(OBJEXT): \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/protobuf_test-parser_unittest.$(OBJEXT): \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.$(OBJEXT): \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.$(OBJEXT): \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.$(OBJEXT): \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.$(OBJEXT): \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.$(OBJEXT): \ + google/protobuf/compiler/java/$(am__dirstamp) \ + google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.$(OBJEXT): \ + google/protobuf/compiler/python/$(am__dirstamp) \ + google/protobuf/compiler/python/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-test_util.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/testing/protobuf_test-googletest.$(OBJEXT): \ + google/protobuf/testing/$(am__dirstamp) \ + google/protobuf/testing/$(DEPDIR)/$(am__dirstamp) +google/protobuf/testing/protobuf_test-file.$(OBJEXT): \ + google/protobuf/testing/$(am__dirstamp) \ + google/protobuf/testing/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest_lite.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest_import_lite.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest_import_public_lite.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest_empty.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest_import.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest_import_public.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest_mset.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest_optimize_for.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest_custom_options.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/protobuf_test-unittest_no_generic_services.pb.$(OBJEXT): \ + google/protobuf/$(am__dirstamp) \ + google/protobuf/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.$(OBJEXT): \ + google/protobuf/compiler/cpp/$(am__dirstamp) \ + google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) protobuf-test$(EXEEXT): $(protobuf_test_OBJECTS) $(protobuf_test_DEPENDENCIES) $(EXTRA_protobuf_test_DEPENDENCIES) @rm -f protobuf-test$(EXEEXT) $(protobuf_test_LINK) $(protobuf_test_OBJECTS) $(protobuf_test_LDADD) $(LIBS) +google/protobuf/compiler/main.$(OBJEXT): \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) protoc$(EXEEXT): $(protoc_OBJECTS) $(protoc_DEPENDENCIES) $(EXTRA_protoc_DEPENDENCIES) @rm -f protoc$(EXEEXT) $(CXXLINK) $(protoc_OBJECTS) $(protoc_LDADD) $(LIBS) +google/protobuf/compiler/test_plugin-mock_code_generator.$(OBJEXT): \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) +google/protobuf/testing/test_plugin-file.$(OBJEXT): \ + google/protobuf/testing/$(am__dirstamp) \ + google/protobuf/testing/$(DEPDIR)/$(am__dirstamp) +google/protobuf/compiler/test_plugin-test_plugin.$(OBJEXT): \ + google/protobuf/compiler/$(am__dirstamp) \ + google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) test_plugin$(EXEEXT): $(test_plugin_OBJECTS) $(test_plugin_DEPENDENCIES) $(EXTRA_test_plugin_DEPENDENCIES) @rm -f test_plugin$(EXEEXT) $(CXXLINK) $(test_plugin_OBJECTS) $(test_plugin_LDADD) $(LIBS) +google/protobuf/testing/zcgunzip.$(OBJEXT): \ + google/protobuf/testing/$(am__dirstamp) \ + google/protobuf/testing/$(DEPDIR)/$(am__dirstamp) zcgunzip$(EXEEXT): $(zcgunzip_OBJECTS) $(zcgunzip_DEPENDENCIES) $(EXTRA_zcgunzip_DEPENDENCIES) @rm -f zcgunzip$(EXEEXT) $(CXXLINK) $(zcgunzip_OBJECTS) $(zcgunzip_LDADD) $(LIBS) +google/protobuf/testing/zcgzip.$(OBJEXT): \ + google/protobuf/testing/$(am__dirstamp) \ + google/protobuf/testing/$(DEPDIR)/$(am__dirstamp) zcgzip$(EXEEXT): $(zcgzip_OBJECTS) $(zcgzip_DEPENDENCIES) $(EXTRA_zcgzip_DEPENDENCIES) @rm -f zcgzip$(EXEEXT) $(CXXLINK) $(zcgzip_OBJECTS) $(zcgzip_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) + -rm -f google/protobuf/compiler/code_generator.$(OBJEXT) + -rm -f google/protobuf/compiler/code_generator.lo + -rm -f google/protobuf/compiler/command_line_interface.$(OBJEXT) + -rm -f google/protobuf/compiler/command_line_interface.lo + -rm -f google/protobuf/compiler/cpp/cpp_enum.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/cpp_enum.lo + -rm -f google/protobuf/compiler/cpp/cpp_enum_field.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/cpp_enum_field.lo + -rm -f google/protobuf/compiler/cpp/cpp_extension.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/cpp_extension.lo + -rm -f google/protobuf/compiler/cpp/cpp_field.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/cpp_field.lo + -rm -f google/protobuf/compiler/cpp/cpp_file.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/cpp_file.lo + -rm -f google/protobuf/compiler/cpp/cpp_generator.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/cpp_generator.lo + -rm -f google/protobuf/compiler/cpp/cpp_helpers.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/cpp_helpers.lo + -rm -f google/protobuf/compiler/cpp/cpp_message.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/cpp_message.lo + -rm -f google/protobuf/compiler/cpp/cpp_message_field.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/cpp_message_field.lo + -rm -f google/protobuf/compiler/cpp/cpp_primitive_field.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/cpp_primitive_field.lo + -rm -f google/protobuf/compiler/cpp/cpp_service.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/cpp_service.lo + -rm -f google/protobuf/compiler/cpp/cpp_string_field.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/cpp_string_field.lo + -rm -f google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.$(OBJEXT) + -rm -f google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.$(OBJEXT) + -rm -f google/protobuf/compiler/importer.$(OBJEXT) + -rm -f google/protobuf/compiler/importer.lo + -rm -f google/protobuf/compiler/java/java_context.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_context.lo + -rm -f google/protobuf/compiler/java/java_doc_comment.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_doc_comment.lo + -rm -f google/protobuf/compiler/java/java_enum.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_enum.lo + -rm -f google/protobuf/compiler/java/java_enum_field.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_enum_field.lo + -rm -f google/protobuf/compiler/java/java_extension.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_extension.lo + -rm -f google/protobuf/compiler/java/java_field.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_field.lo + -rm -f google/protobuf/compiler/java/java_file.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_file.lo + -rm -f google/protobuf/compiler/java/java_generator.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_generator.lo + -rm -f google/protobuf/compiler/java/java_generator_factory.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_generator_factory.lo + -rm -f google/protobuf/compiler/java/java_helpers.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_helpers.lo + -rm -f google/protobuf/compiler/java/java_lazy_message_field.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_lazy_message_field.lo + -rm -f google/protobuf/compiler/java/java_message.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_message.lo + -rm -f google/protobuf/compiler/java/java_message_field.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_message_field.lo + -rm -f google/protobuf/compiler/java/java_name_resolver.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_name_resolver.lo + -rm -f google/protobuf/compiler/java/java_primitive_field.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_primitive_field.lo + -rm -f google/protobuf/compiler/java/java_service.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_service.lo + -rm -f google/protobuf/compiler/java/java_shared_code_generator.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_shared_code_generator.lo + -rm -f google/protobuf/compiler/java/java_string_field.$(OBJEXT) + -rm -f google/protobuf/compiler/java/java_string_field.lo + -rm -f google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.$(OBJEXT) + -rm -f google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.$(OBJEXT) + -rm -f google/protobuf/compiler/javamicro/javamicro_enum.$(OBJEXT) + -rm -f google/protobuf/compiler/javamicro/javamicro_enum.lo + -rm -f google/protobuf/compiler/javamicro/javamicro_enum_field.$(OBJEXT) + -rm -f google/protobuf/compiler/javamicro/javamicro_enum_field.lo + -rm -f google/protobuf/compiler/javamicro/javamicro_field.$(OBJEXT) + -rm -f google/protobuf/compiler/javamicro/javamicro_field.lo + -rm -f google/protobuf/compiler/javamicro/javamicro_file.$(OBJEXT) + -rm -f google/protobuf/compiler/javamicro/javamicro_file.lo + -rm -f google/protobuf/compiler/javamicro/javamicro_generator.$(OBJEXT) + -rm -f google/protobuf/compiler/javamicro/javamicro_generator.lo + -rm -f google/protobuf/compiler/javamicro/javamicro_helpers.$(OBJEXT) + -rm -f google/protobuf/compiler/javamicro/javamicro_helpers.lo + -rm -f google/protobuf/compiler/javamicro/javamicro_message.$(OBJEXT) + -rm -f google/protobuf/compiler/javamicro/javamicro_message.lo + -rm -f google/protobuf/compiler/javamicro/javamicro_message_field.$(OBJEXT) + -rm -f google/protobuf/compiler/javamicro/javamicro_message_field.lo + -rm -f google/protobuf/compiler/javamicro/javamicro_primitive_field.$(OBJEXT) + -rm -f google/protobuf/compiler/javamicro/javamicro_primitive_field.lo + -rm -f google/protobuf/compiler/javanano/javanano_enum.$(OBJEXT) + -rm -f google/protobuf/compiler/javanano/javanano_enum.lo + -rm -f google/protobuf/compiler/javanano/javanano_enum_field.$(OBJEXT) + -rm -f google/protobuf/compiler/javanano/javanano_enum_field.lo + -rm -f google/protobuf/compiler/javanano/javanano_extension.$(OBJEXT) + -rm -f google/protobuf/compiler/javanano/javanano_extension.lo + -rm -f google/protobuf/compiler/javanano/javanano_field.$(OBJEXT) + -rm -f google/protobuf/compiler/javanano/javanano_field.lo + -rm -f google/protobuf/compiler/javanano/javanano_file.$(OBJEXT) + -rm -f google/protobuf/compiler/javanano/javanano_file.lo + -rm -f google/protobuf/compiler/javanano/javanano_generator.$(OBJEXT) + -rm -f google/protobuf/compiler/javanano/javanano_generator.lo + -rm -f google/protobuf/compiler/javanano/javanano_helpers.$(OBJEXT) + -rm -f google/protobuf/compiler/javanano/javanano_helpers.lo + -rm -f google/protobuf/compiler/javanano/javanano_message.$(OBJEXT) + -rm -f google/protobuf/compiler/javanano/javanano_message.lo + -rm -f google/protobuf/compiler/javanano/javanano_message_field.$(OBJEXT) + -rm -f google/protobuf/compiler/javanano/javanano_message_field.lo + -rm -f google/protobuf/compiler/javanano/javanano_primitive_field.$(OBJEXT) + -rm -f google/protobuf/compiler/javanano/javanano_primitive_field.lo + -rm -f google/protobuf/compiler/main.$(OBJEXT) + -rm -f google/protobuf/compiler/parser.$(OBJEXT) + -rm -f google/protobuf/compiler/parser.lo + -rm -f google/protobuf/compiler/plugin.$(OBJEXT) + -rm -f google/protobuf/compiler/plugin.lo + -rm -f google/protobuf/compiler/plugin.pb.$(OBJEXT) + -rm -f google/protobuf/compiler/plugin.pb.lo + -rm -f google/protobuf/compiler/protobuf_test-command_line_interface_unittest.$(OBJEXT) + -rm -f google/protobuf/compiler/protobuf_test-importer_unittest.$(OBJEXT) + -rm -f google/protobuf/compiler/protobuf_test-mock_code_generator.$(OBJEXT) + -rm -f google/protobuf/compiler/protobuf_test-parser_unittest.$(OBJEXT) + -rm -f google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.$(OBJEXT) + -rm -f google/protobuf/compiler/python/python_generator.$(OBJEXT) + -rm -f google/protobuf/compiler/python/python_generator.lo + -rm -f google/protobuf/compiler/subprocess.$(OBJEXT) + -rm -f google/protobuf/compiler/subprocess.lo + -rm -f google/protobuf/compiler/test_plugin-mock_code_generator.$(OBJEXT) + -rm -f google/protobuf/compiler/test_plugin-test_plugin.$(OBJEXT) + -rm -f google/protobuf/compiler/zip_writer.$(OBJEXT) + -rm -f google/protobuf/compiler/zip_writer.lo + -rm -f google/protobuf/descriptor.$(OBJEXT) + -rm -f google/protobuf/descriptor.lo + -rm -f google/protobuf/descriptor.pb.$(OBJEXT) + -rm -f google/protobuf/descriptor.pb.lo + -rm -f google/protobuf/descriptor_database.$(OBJEXT) + -rm -f google/protobuf/descriptor_database.lo + -rm -f google/protobuf/dynamic_message.$(OBJEXT) + -rm -f google/protobuf/dynamic_message.lo + -rm -f google/protobuf/extension_set.$(OBJEXT) + -rm -f google/protobuf/extension_set.lo + -rm -f google/protobuf/extension_set_heavy.$(OBJEXT) + -rm -f google/protobuf/extension_set_heavy.lo + -rm -f google/protobuf/generated_message_reflection.$(OBJEXT) + -rm -f google/protobuf/generated_message_reflection.lo + -rm -f google/protobuf/generated_message_util.$(OBJEXT) + -rm -f google/protobuf/generated_message_util.lo + -rm -f google/protobuf/io/coded_stream.$(OBJEXT) + -rm -f google/protobuf/io/coded_stream.lo + -rm -f google/protobuf/io/gzip_stream.$(OBJEXT) + -rm -f google/protobuf/io/gzip_stream.lo + -rm -f google/protobuf/io/printer.$(OBJEXT) + -rm -f google/protobuf/io/printer.lo + -rm -f google/protobuf/io/protobuf_test-coded_stream_unittest.$(OBJEXT) + -rm -f google/protobuf/io/protobuf_test-printer_unittest.$(OBJEXT) + -rm -f google/protobuf/io/protobuf_test-tokenizer_unittest.$(OBJEXT) + -rm -f google/protobuf/io/protobuf_test-zero_copy_stream_unittest.$(OBJEXT) + -rm -f google/protobuf/io/strtod.$(OBJEXT) + -rm -f google/protobuf/io/strtod.lo + -rm -f google/protobuf/io/tokenizer.$(OBJEXT) + -rm -f google/protobuf/io/tokenizer.lo + -rm -f google/protobuf/io/zero_copy_stream.$(OBJEXT) + -rm -f google/protobuf/io/zero_copy_stream.lo + -rm -f google/protobuf/io/zero_copy_stream_impl.$(OBJEXT) + -rm -f google/protobuf/io/zero_copy_stream_impl.lo + -rm -f google/protobuf/io/zero_copy_stream_impl_lite.$(OBJEXT) + -rm -f google/protobuf/io/zero_copy_stream_impl_lite.lo + -rm -f google/protobuf/message.$(OBJEXT) + -rm -f google/protobuf/message.lo + -rm -f google/protobuf/message_lite.$(OBJEXT) + -rm -f google/protobuf/message_lite.lo + -rm -f google/protobuf/protobuf_lazy_descriptor_test-test_util.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lite_test-lite_unittest.$(OBJEXT) + -rm -f google/protobuf/protobuf_lite_test-test_util_lite.$(OBJEXT) + -rm -f google/protobuf/protobuf_lite_test-unittest_import_lite.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_lite_test-unittest_lite.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-descriptor_database_unittest.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-descriptor_unittest.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-dynamic_message_unittest.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-extension_set_unittest.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-generated_message_reflection_unittest.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-message_unittest.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-reflection_ops_unittest.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-repeated_field_reflection_unittest.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-repeated_field_unittest.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-test_util.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-text_format_unittest.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest_custom_options.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest_empty.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest_import.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest_import_lite.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest_import_public.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest_import_public_lite.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest_lite.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest_mset.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest_no_generic_services.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unittest_optimize_for.pb.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-unknown_field_set_unittest.$(OBJEXT) + -rm -f google/protobuf/protobuf_test-wire_format_unittest.$(OBJEXT) + -rm -f google/protobuf/reflection_ops.$(OBJEXT) + -rm -f google/protobuf/reflection_ops.lo + -rm -f google/protobuf/repeated_field.$(OBJEXT) + -rm -f google/protobuf/repeated_field.lo + -rm -f google/protobuf/service.$(OBJEXT) + -rm -f google/protobuf/service.lo + -rm -f google/protobuf/stubs/atomicops_internals_x86_gcc.$(OBJEXT) + -rm -f google/protobuf/stubs/atomicops_internals_x86_gcc.lo + -rm -f google/protobuf/stubs/atomicops_internals_x86_msvc.$(OBJEXT) + -rm -f google/protobuf/stubs/atomicops_internals_x86_msvc.lo + -rm -f google/protobuf/stubs/common.$(OBJEXT) + -rm -f google/protobuf/stubs/common.lo + -rm -f google/protobuf/stubs/once.$(OBJEXT) + -rm -f google/protobuf/stubs/once.lo + -rm -f google/protobuf/stubs/protobuf_test-common_unittest.$(OBJEXT) + -rm -f google/protobuf/stubs/protobuf_test-once_unittest.$(OBJEXT) + -rm -f google/protobuf/stubs/protobuf_test-stringprintf_unittest.$(OBJEXT) + -rm -f google/protobuf/stubs/protobuf_test-structurally_valid_unittest.$(OBJEXT) + -rm -f google/protobuf/stubs/protobuf_test-strutil_unittest.$(OBJEXT) + -rm -f google/protobuf/stubs/protobuf_test-template_util_unittest.$(OBJEXT) + -rm -f google/protobuf/stubs/protobuf_test-type_traits_unittest.$(OBJEXT) + -rm -f google/protobuf/stubs/stringprintf.$(OBJEXT) + -rm -f google/protobuf/stubs/stringprintf.lo + -rm -f google/protobuf/stubs/structurally_valid.$(OBJEXT) + -rm -f google/protobuf/stubs/structurally_valid.lo + -rm -f google/protobuf/stubs/strutil.$(OBJEXT) + -rm -f google/protobuf/stubs/strutil.lo + -rm -f google/protobuf/stubs/substitute.$(OBJEXT) + -rm -f google/protobuf/stubs/substitute.lo + -rm -f google/protobuf/testing/protobuf_lazy_descriptor_test-file.$(OBJEXT) + -rm -f google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.$(OBJEXT) + -rm -f google/protobuf/testing/protobuf_test-file.$(OBJEXT) + -rm -f google/protobuf/testing/protobuf_test-googletest.$(OBJEXT) + -rm -f google/protobuf/testing/test_plugin-file.$(OBJEXT) + -rm -f google/protobuf/testing/zcgunzip.$(OBJEXT) + -rm -f google/protobuf/testing/zcgzip.$(OBJEXT) + -rm -f google/protobuf/text_format.$(OBJEXT) + -rm -f google/protobuf/text_format.lo + -rm -f google/protobuf/unknown_field_set.$(OBJEXT) + -rm -f google/protobuf/unknown_field_set.lo + -rm -f google/protobuf/wire_format.$(OBJEXT) + -rm -f google/protobuf/wire_format.lo + -rm -f google/protobuf/wire_format_lite.$(OBJEXT) + -rm -f google/protobuf/wire_format_lite.lo distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/code_generator.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coded_stream.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/command_line_interface.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_enum.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_enum_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_extension.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_file.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_generator.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_helpers.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_message.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_message_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_primitive_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_service.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpp_string_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/descriptor.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/descriptor.pb.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/descriptor_database.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynamic_message.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extension_set.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extension_set_heavy.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generated_message_reflection.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generated_message_util.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gzip_stream.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/importer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_enum.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_enum_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_extension.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_file.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_generator.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_helpers.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_message.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_message_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_primitive_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_service.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_enum.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_enum_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_file.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_generator.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_helpers.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_message.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_message_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_primitive_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javanano_enum.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javanano_enum_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javanano_extension.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javanano_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javanano_file.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javanano_generator.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javanano_helpers.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javanano_message.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javanano_message_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javanano_primitive_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message_lite.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/once.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.pb.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-file.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lite_test-lite_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lite_test-test_util_lite.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-coded_stream_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-command_line_interface_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-common_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-cpp_plugin_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-cpp_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-descriptor_database_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-descriptor_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-dynamic_message_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-extension_set_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-file.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-googletest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-importer_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-java_plugin_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-message_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-mock_code_generator.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-once_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-parser_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-printer_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-python_plugin_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-reflection_ops_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-repeated_field_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-structurally_valid_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-strutil_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-test_util.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-text_format_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-tokenizer_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-unittest.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-unittest_custom_options.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-unittest_empty.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-unittest_import.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-unittest_import_lite.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-unittest_lite.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-unittest_mset.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-unknown_field_set_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-wire_format_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/python_generator.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reflection_ops.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/repeated_field.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/service.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/structurally_valid.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strutil.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subprocess.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/substitute.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin-file.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin-mock_code_generator.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin-test_plugin.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text_format.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tokenizer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unknown_field_set.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wire_format.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wire_format_lite.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zcgunzip.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zcgzip.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zero_copy_stream.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zero_copy_stream_impl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zero_copy_stream_impl_lite.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zip_writer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/descriptor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/descriptor.pb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/descriptor_database.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/dynamic_message.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/extension_set.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/extension_set_heavy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/generated_message_reflection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/generated_message_util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/message.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/message_lite.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lite_test-lite_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lite_test-test_util_lite.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_public_lite.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-descriptor_database_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-descriptor_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-dynamic_message_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-extension_set_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-message_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-reflection_ops_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_reflection_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-test_util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-text_format_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest_custom_options.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest_empty.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest_import.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_lite.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public_lite.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest_mset.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-unknown_field_set_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/protobuf_test-wire_format_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/reflection_ops.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/repeated_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/service.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/text_format.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/unknown_field_set.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/wire_format.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/$(DEPDIR)/wire_format_lite.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/code_generator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/command_line_interface.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/importer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/parser.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/plugin.pb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/protobuf_test-command_line_interface_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/protobuf_test-importer_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/protobuf_test-mock_code_generator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/protobuf_test-parser_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/subprocess.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/test_plugin-mock_code_generator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/test_plugin-test_plugin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/$(DEPDIR)/zip_writer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/cpp_enum.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/cpp_enum_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/cpp_extension.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/cpp_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/cpp_file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/cpp_generator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/cpp_helpers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/cpp_message.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/cpp_message_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/cpp_primitive_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/cpp_service.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/cpp_string_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_plugin_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_context.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_doc_comment.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_enum.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_enum_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_extension.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_generator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_generator_factory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_helpers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_lazy_message_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_message.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_message_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_name_resolver.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_primitive_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_service.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_shared_code_generator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/java_string_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_doc_comment_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_plugin_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javamicro/$(DEPDIR)/javamicro_enum.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javamicro/$(DEPDIR)/javamicro_enum_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javamicro/$(DEPDIR)/javamicro_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javamicro/$(DEPDIR)/javamicro_file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javamicro/$(DEPDIR)/javamicro_generator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javamicro/$(DEPDIR)/javamicro_helpers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javamicro/$(DEPDIR)/javamicro_message.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javamicro/$(DEPDIR)/javamicro_message_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javamicro/$(DEPDIR)/javamicro_primitive_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javanano/$(DEPDIR)/javanano_enum.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javanano/$(DEPDIR)/javanano_enum_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javanano/$(DEPDIR)/javanano_extension.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javanano/$(DEPDIR)/javanano_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javanano/$(DEPDIR)/javanano_file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javanano/$(DEPDIR)/javanano_generator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javanano/$(DEPDIR)/javanano_helpers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javanano/$(DEPDIR)/javanano_message.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javanano/$(DEPDIR)/javanano_message_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/javanano/$(DEPDIR)/javanano_primitive_field.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/python/$(DEPDIR)/protobuf_test-python_plugin_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/compiler/python/$(DEPDIR)/python_generator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/io/$(DEPDIR)/coded_stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/io/$(DEPDIR)/gzip_stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/io/$(DEPDIR)/printer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/io/$(DEPDIR)/protobuf_test-coded_stream_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/io/$(DEPDIR)/protobuf_test-printer_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/io/$(DEPDIR)/protobuf_test-tokenizer_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/io/$(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/io/$(DEPDIR)/strtod.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/io/$(DEPDIR)/tokenizer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/io/$(DEPDIR)/zero_copy_stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/io/$(DEPDIR)/zero_copy_stream_impl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/io/$(DEPDIR)/zero_copy_stream_impl_lite.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/atomicops_internals_x86_gcc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/atomicops_internals_x86_msvc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/common.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/once.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/protobuf_test-common_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/protobuf_test-once_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/protobuf_test-stringprintf_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/protobuf_test-structurally_valid_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/protobuf_test-strutil_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/protobuf_test-template_util_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/protobuf_test-type_traits_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/stringprintf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/structurally_valid.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/strutil.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/stubs/$(DEPDIR)/substitute.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/testing/$(DEPDIR)/protobuf_test-file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/testing/$(DEPDIR)/protobuf_test-googletest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/testing/$(DEPDIR)/test_plugin-file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/testing/$(DEPDIR)/zcgunzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@google/protobuf/testing/$(DEPDIR)/zcgzip.Po@am__quote@ .cc.o: -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cc.obj: -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: -@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< -common.lo: google/protobuf/stubs/common.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT common.lo -MD -MP -MF $(DEPDIR)/common.Tpo -c -o common.lo `test -f 'google/protobuf/stubs/common.cc' || echo '$(srcdir)/'`google/protobuf/stubs/common.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/common.Tpo $(DEPDIR)/common.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/common.cc' object='common.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o common.lo `test -f 'google/protobuf/stubs/common.cc' || echo '$(srcdir)/'`google/protobuf/stubs/common.cc - -once.lo: google/protobuf/stubs/once.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT once.lo -MD -MP -MF $(DEPDIR)/once.Tpo -c -o once.lo `test -f 'google/protobuf/stubs/once.cc' || echo '$(srcdir)/'`google/protobuf/stubs/once.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/once.Tpo $(DEPDIR)/once.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/once.cc' object='once.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o once.lo `test -f 'google/protobuf/stubs/once.cc' || echo '$(srcdir)/'`google/protobuf/stubs/once.cc - -hash.lo: google/protobuf/stubs/hash.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT hash.lo -MD -MP -MF $(DEPDIR)/hash.Tpo -c -o hash.lo `test -f 'google/protobuf/stubs/hash.cc' || echo '$(srcdir)/'`google/protobuf/stubs/hash.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/hash.Tpo $(DEPDIR)/hash.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/hash.cc' object='hash.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o hash.lo `test -f 'google/protobuf/stubs/hash.cc' || echo '$(srcdir)/'`google/protobuf/stubs/hash.cc - -extension_set.lo: google/protobuf/extension_set.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT extension_set.lo -MD -MP -MF $(DEPDIR)/extension_set.Tpo -c -o extension_set.lo `test -f 'google/protobuf/extension_set.cc' || echo '$(srcdir)/'`google/protobuf/extension_set.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/extension_set.Tpo $(DEPDIR)/extension_set.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/extension_set.cc' object='extension_set.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o extension_set.lo `test -f 'google/protobuf/extension_set.cc' || echo '$(srcdir)/'`google/protobuf/extension_set.cc - -generated_message_util.lo: google/protobuf/generated_message_util.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT generated_message_util.lo -MD -MP -MF $(DEPDIR)/generated_message_util.Tpo -c -o generated_message_util.lo `test -f 'google/protobuf/generated_message_util.cc' || echo '$(srcdir)/'`google/protobuf/generated_message_util.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/generated_message_util.Tpo $(DEPDIR)/generated_message_util.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/generated_message_util.cc' object='generated_message_util.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o generated_message_util.lo `test -f 'google/protobuf/generated_message_util.cc' || echo '$(srcdir)/'`google/protobuf/generated_message_util.cc - -message_lite.lo: google/protobuf/message_lite.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT message_lite.lo -MD -MP -MF $(DEPDIR)/message_lite.Tpo -c -o message_lite.lo `test -f 'google/protobuf/message_lite.cc' || echo '$(srcdir)/'`google/protobuf/message_lite.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/message_lite.Tpo $(DEPDIR)/message_lite.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/message_lite.cc' object='message_lite.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o message_lite.lo `test -f 'google/protobuf/message_lite.cc' || echo '$(srcdir)/'`google/protobuf/message_lite.cc - -repeated_field.lo: google/protobuf/repeated_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT repeated_field.lo -MD -MP -MF $(DEPDIR)/repeated_field.Tpo -c -o repeated_field.lo `test -f 'google/protobuf/repeated_field.cc' || echo '$(srcdir)/'`google/protobuf/repeated_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/repeated_field.Tpo $(DEPDIR)/repeated_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/repeated_field.cc' object='repeated_field.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o repeated_field.lo `test -f 'google/protobuf/repeated_field.cc' || echo '$(srcdir)/'`google/protobuf/repeated_field.cc - -wire_format_lite.lo: google/protobuf/wire_format_lite.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT wire_format_lite.lo -MD -MP -MF $(DEPDIR)/wire_format_lite.Tpo -c -o wire_format_lite.lo `test -f 'google/protobuf/wire_format_lite.cc' || echo '$(srcdir)/'`google/protobuf/wire_format_lite.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/wire_format_lite.Tpo $(DEPDIR)/wire_format_lite.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/wire_format_lite.cc' object='wire_format_lite.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o wire_format_lite.lo `test -f 'google/protobuf/wire_format_lite.cc' || echo '$(srcdir)/'`google/protobuf/wire_format_lite.cc - -coded_stream.lo: google/protobuf/io/coded_stream.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT coded_stream.lo -MD -MP -MF $(DEPDIR)/coded_stream.Tpo -c -o coded_stream.lo `test -f 'google/protobuf/io/coded_stream.cc' || echo '$(srcdir)/'`google/protobuf/io/coded_stream.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/coded_stream.Tpo $(DEPDIR)/coded_stream.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/coded_stream.cc' object='coded_stream.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o coded_stream.lo `test -f 'google/protobuf/io/coded_stream.cc' || echo '$(srcdir)/'`google/protobuf/io/coded_stream.cc - -zero_copy_stream.lo: google/protobuf/io/zero_copy_stream.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zero_copy_stream.lo -MD -MP -MF $(DEPDIR)/zero_copy_stream.Tpo -c -o zero_copy_stream.lo `test -f 'google/protobuf/io/zero_copy_stream.cc' || echo '$(srcdir)/'`google/protobuf/io/zero_copy_stream.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/zero_copy_stream.Tpo $(DEPDIR)/zero_copy_stream.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/zero_copy_stream.cc' object='zero_copy_stream.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zero_copy_stream.lo `test -f 'google/protobuf/io/zero_copy_stream.cc' || echo '$(srcdir)/'`google/protobuf/io/zero_copy_stream.cc - -zero_copy_stream_impl_lite.lo: google/protobuf/io/zero_copy_stream_impl_lite.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zero_copy_stream_impl_lite.lo -MD -MP -MF $(DEPDIR)/zero_copy_stream_impl_lite.Tpo -c -o zero_copy_stream_impl_lite.lo `test -f 'google/protobuf/io/zero_copy_stream_impl_lite.cc' || echo '$(srcdir)/'`google/protobuf/io/zero_copy_stream_impl_lite.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/zero_copy_stream_impl_lite.Tpo $(DEPDIR)/zero_copy_stream_impl_lite.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/zero_copy_stream_impl_lite.cc' object='zero_copy_stream_impl_lite.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zero_copy_stream_impl_lite.lo `test -f 'google/protobuf/io/zero_copy_stream_impl_lite.cc' || echo '$(srcdir)/'`google/protobuf/io/zero_copy_stream_impl_lite.cc - -strutil.lo: google/protobuf/stubs/strutil.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT strutil.lo -MD -MP -MF $(DEPDIR)/strutil.Tpo -c -o strutil.lo `test -f 'google/protobuf/stubs/strutil.cc' || echo '$(srcdir)/'`google/protobuf/stubs/strutil.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/strutil.Tpo $(DEPDIR)/strutil.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/strutil.cc' object='strutil.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o strutil.lo `test -f 'google/protobuf/stubs/strutil.cc' || echo '$(srcdir)/'`google/protobuf/stubs/strutil.cc - -substitute.lo: google/protobuf/stubs/substitute.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT substitute.lo -MD -MP -MF $(DEPDIR)/substitute.Tpo -c -o substitute.lo `test -f 'google/protobuf/stubs/substitute.cc' || echo '$(srcdir)/'`google/protobuf/stubs/substitute.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/substitute.Tpo $(DEPDIR)/substitute.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/substitute.cc' object='substitute.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o substitute.lo `test -f 'google/protobuf/stubs/substitute.cc' || echo '$(srcdir)/'`google/protobuf/stubs/substitute.cc - -structurally_valid.lo: google/protobuf/stubs/structurally_valid.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT structurally_valid.lo -MD -MP -MF $(DEPDIR)/structurally_valid.Tpo -c -o structurally_valid.lo `test -f 'google/protobuf/stubs/structurally_valid.cc' || echo '$(srcdir)/'`google/protobuf/stubs/structurally_valid.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/structurally_valid.Tpo $(DEPDIR)/structurally_valid.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/structurally_valid.cc' object='structurally_valid.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o structurally_valid.lo `test -f 'google/protobuf/stubs/structurally_valid.cc' || echo '$(srcdir)/'`google/protobuf/stubs/structurally_valid.cc - -descriptor.lo: google/protobuf/descriptor.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT descriptor.lo -MD -MP -MF $(DEPDIR)/descriptor.Tpo -c -o descriptor.lo `test -f 'google/protobuf/descriptor.cc' || echo '$(srcdir)/'`google/protobuf/descriptor.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/descriptor.Tpo $(DEPDIR)/descriptor.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/descriptor.cc' object='descriptor.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o descriptor.lo `test -f 'google/protobuf/descriptor.cc' || echo '$(srcdir)/'`google/protobuf/descriptor.cc - -descriptor.pb.lo: google/protobuf/descriptor.pb.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT descriptor.pb.lo -MD -MP -MF $(DEPDIR)/descriptor.pb.Tpo -c -o descriptor.pb.lo `test -f 'google/protobuf/descriptor.pb.cc' || echo '$(srcdir)/'`google/protobuf/descriptor.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/descriptor.pb.Tpo $(DEPDIR)/descriptor.pb.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/descriptor.pb.cc' object='descriptor.pb.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o descriptor.pb.lo `test -f 'google/protobuf/descriptor.pb.cc' || echo '$(srcdir)/'`google/protobuf/descriptor.pb.cc - -descriptor_database.lo: google/protobuf/descriptor_database.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT descriptor_database.lo -MD -MP -MF $(DEPDIR)/descriptor_database.Tpo -c -o descriptor_database.lo `test -f 'google/protobuf/descriptor_database.cc' || echo '$(srcdir)/'`google/protobuf/descriptor_database.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/descriptor_database.Tpo $(DEPDIR)/descriptor_database.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/descriptor_database.cc' object='descriptor_database.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o descriptor_database.lo `test -f 'google/protobuf/descriptor_database.cc' || echo '$(srcdir)/'`google/protobuf/descriptor_database.cc - -dynamic_message.lo: google/protobuf/dynamic_message.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT dynamic_message.lo -MD -MP -MF $(DEPDIR)/dynamic_message.Tpo -c -o dynamic_message.lo `test -f 'google/protobuf/dynamic_message.cc' || echo '$(srcdir)/'`google/protobuf/dynamic_message.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/dynamic_message.Tpo $(DEPDIR)/dynamic_message.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/dynamic_message.cc' object='dynamic_message.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o dynamic_message.lo `test -f 'google/protobuf/dynamic_message.cc' || echo '$(srcdir)/'`google/protobuf/dynamic_message.cc - -extension_set_heavy.lo: google/protobuf/extension_set_heavy.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT extension_set_heavy.lo -MD -MP -MF $(DEPDIR)/extension_set_heavy.Tpo -c -o extension_set_heavy.lo `test -f 'google/protobuf/extension_set_heavy.cc' || echo '$(srcdir)/'`google/protobuf/extension_set_heavy.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/extension_set_heavy.Tpo $(DEPDIR)/extension_set_heavy.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/extension_set_heavy.cc' object='extension_set_heavy.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o extension_set_heavy.lo `test -f 'google/protobuf/extension_set_heavy.cc' || echo '$(srcdir)/'`google/protobuf/extension_set_heavy.cc - -generated_message_reflection.lo: google/protobuf/generated_message_reflection.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT generated_message_reflection.lo -MD -MP -MF $(DEPDIR)/generated_message_reflection.Tpo -c -o generated_message_reflection.lo `test -f 'google/protobuf/generated_message_reflection.cc' || echo '$(srcdir)/'`google/protobuf/generated_message_reflection.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/generated_message_reflection.Tpo $(DEPDIR)/generated_message_reflection.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/generated_message_reflection.cc' object='generated_message_reflection.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o generated_message_reflection.lo `test -f 'google/protobuf/generated_message_reflection.cc' || echo '$(srcdir)/'`google/protobuf/generated_message_reflection.cc - -message.lo: google/protobuf/message.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT message.lo -MD -MP -MF $(DEPDIR)/message.Tpo -c -o message.lo `test -f 'google/protobuf/message.cc' || echo '$(srcdir)/'`google/protobuf/message.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/message.Tpo $(DEPDIR)/message.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/message.cc' object='message.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o message.lo `test -f 'google/protobuf/message.cc' || echo '$(srcdir)/'`google/protobuf/message.cc - -reflection_ops.lo: google/protobuf/reflection_ops.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT reflection_ops.lo -MD -MP -MF $(DEPDIR)/reflection_ops.Tpo -c -o reflection_ops.lo `test -f 'google/protobuf/reflection_ops.cc' || echo '$(srcdir)/'`google/protobuf/reflection_ops.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/reflection_ops.Tpo $(DEPDIR)/reflection_ops.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/reflection_ops.cc' object='reflection_ops.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o reflection_ops.lo `test -f 'google/protobuf/reflection_ops.cc' || echo '$(srcdir)/'`google/protobuf/reflection_ops.cc - -service.lo: google/protobuf/service.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT service.lo -MD -MP -MF $(DEPDIR)/service.Tpo -c -o service.lo `test -f 'google/protobuf/service.cc' || echo '$(srcdir)/'`google/protobuf/service.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/service.Tpo $(DEPDIR)/service.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/service.cc' object='service.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o service.lo `test -f 'google/protobuf/service.cc' || echo '$(srcdir)/'`google/protobuf/service.cc - -text_format.lo: google/protobuf/text_format.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT text_format.lo -MD -MP -MF $(DEPDIR)/text_format.Tpo -c -o text_format.lo `test -f 'google/protobuf/text_format.cc' || echo '$(srcdir)/'`google/protobuf/text_format.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/text_format.Tpo $(DEPDIR)/text_format.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/text_format.cc' object='text_format.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o text_format.lo `test -f 'google/protobuf/text_format.cc' || echo '$(srcdir)/'`google/protobuf/text_format.cc - -unknown_field_set.lo: google/protobuf/unknown_field_set.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT unknown_field_set.lo -MD -MP -MF $(DEPDIR)/unknown_field_set.Tpo -c -o unknown_field_set.lo `test -f 'google/protobuf/unknown_field_set.cc' || echo '$(srcdir)/'`google/protobuf/unknown_field_set.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/unknown_field_set.Tpo $(DEPDIR)/unknown_field_set.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unknown_field_set.cc' object='unknown_field_set.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o unknown_field_set.lo `test -f 'google/protobuf/unknown_field_set.cc' || echo '$(srcdir)/'`google/protobuf/unknown_field_set.cc - -wire_format.lo: google/protobuf/wire_format.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT wire_format.lo -MD -MP -MF $(DEPDIR)/wire_format.Tpo -c -o wire_format.lo `test -f 'google/protobuf/wire_format.cc' || echo '$(srcdir)/'`google/protobuf/wire_format.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/wire_format.Tpo $(DEPDIR)/wire_format.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/wire_format.cc' object='wire_format.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o wire_format.lo `test -f 'google/protobuf/wire_format.cc' || echo '$(srcdir)/'`google/protobuf/wire_format.cc - -gzip_stream.lo: google/protobuf/io/gzip_stream.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gzip_stream.lo -MD -MP -MF $(DEPDIR)/gzip_stream.Tpo -c -o gzip_stream.lo `test -f 'google/protobuf/io/gzip_stream.cc' || echo '$(srcdir)/'`google/protobuf/io/gzip_stream.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/gzip_stream.Tpo $(DEPDIR)/gzip_stream.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/gzip_stream.cc' object='gzip_stream.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gzip_stream.lo `test -f 'google/protobuf/io/gzip_stream.cc' || echo '$(srcdir)/'`google/protobuf/io/gzip_stream.cc - -printer.lo: google/protobuf/io/printer.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT printer.lo -MD -MP -MF $(DEPDIR)/printer.Tpo -c -o printer.lo `test -f 'google/protobuf/io/printer.cc' || echo '$(srcdir)/'`google/protobuf/io/printer.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/printer.Tpo $(DEPDIR)/printer.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/printer.cc' object='printer.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o printer.lo `test -f 'google/protobuf/io/printer.cc' || echo '$(srcdir)/'`google/protobuf/io/printer.cc - -tokenizer.lo: google/protobuf/io/tokenizer.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tokenizer.lo -MD -MP -MF $(DEPDIR)/tokenizer.Tpo -c -o tokenizer.lo `test -f 'google/protobuf/io/tokenizer.cc' || echo '$(srcdir)/'`google/protobuf/io/tokenizer.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/tokenizer.Tpo $(DEPDIR)/tokenizer.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/tokenizer.cc' object='tokenizer.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tokenizer.lo `test -f 'google/protobuf/io/tokenizer.cc' || echo '$(srcdir)/'`google/protobuf/io/tokenizer.cc - -zero_copy_stream_impl.lo: google/protobuf/io/zero_copy_stream_impl.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zero_copy_stream_impl.lo -MD -MP -MF $(DEPDIR)/zero_copy_stream_impl.Tpo -c -o zero_copy_stream_impl.lo `test -f 'google/protobuf/io/zero_copy_stream_impl.cc' || echo '$(srcdir)/'`google/protobuf/io/zero_copy_stream_impl.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/zero_copy_stream_impl.Tpo $(DEPDIR)/zero_copy_stream_impl.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/zero_copy_stream_impl.cc' object='zero_copy_stream_impl.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zero_copy_stream_impl.lo `test -f 'google/protobuf/io/zero_copy_stream_impl.cc' || echo '$(srcdir)/'`google/protobuf/io/zero_copy_stream_impl.cc - -importer.lo: google/protobuf/compiler/importer.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT importer.lo -MD -MP -MF $(DEPDIR)/importer.Tpo -c -o importer.lo `test -f 'google/protobuf/compiler/importer.cc' || echo '$(srcdir)/'`google/protobuf/compiler/importer.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/importer.Tpo $(DEPDIR)/importer.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/importer.cc' object='importer.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o importer.lo `test -f 'google/protobuf/compiler/importer.cc' || echo '$(srcdir)/'`google/protobuf/compiler/importer.cc - -parser.lo: google/protobuf/compiler/parser.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT parser.lo -MD -MP -MF $(DEPDIR)/parser.Tpo -c -o parser.lo `test -f 'google/protobuf/compiler/parser.cc' || echo '$(srcdir)/'`google/protobuf/compiler/parser.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/parser.Tpo $(DEPDIR)/parser.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/parser.cc' object='parser.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o parser.lo `test -f 'google/protobuf/compiler/parser.cc' || echo '$(srcdir)/'`google/protobuf/compiler/parser.cc - -code_generator.lo: google/protobuf/compiler/code_generator.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT code_generator.lo -MD -MP -MF $(DEPDIR)/code_generator.Tpo -c -o code_generator.lo `test -f 'google/protobuf/compiler/code_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/code_generator.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/code_generator.Tpo $(DEPDIR)/code_generator.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/code_generator.cc' object='code_generator.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o code_generator.lo `test -f 'google/protobuf/compiler/code_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/code_generator.cc - -command_line_interface.lo: google/protobuf/compiler/command_line_interface.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT command_line_interface.lo -MD -MP -MF $(DEPDIR)/command_line_interface.Tpo -c -o command_line_interface.lo `test -f 'google/protobuf/compiler/command_line_interface.cc' || echo '$(srcdir)/'`google/protobuf/compiler/command_line_interface.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/command_line_interface.Tpo $(DEPDIR)/command_line_interface.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/command_line_interface.cc' object='command_line_interface.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o command_line_interface.lo `test -f 'google/protobuf/compiler/command_line_interface.cc' || echo '$(srcdir)/'`google/protobuf/compiler/command_line_interface.cc - -plugin.lo: google/protobuf/compiler/plugin.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT plugin.lo -MD -MP -MF $(DEPDIR)/plugin.Tpo -c -o plugin.lo `test -f 'google/protobuf/compiler/plugin.cc' || echo '$(srcdir)/'`google/protobuf/compiler/plugin.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/plugin.Tpo $(DEPDIR)/plugin.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/plugin.cc' object='plugin.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o plugin.lo `test -f 'google/protobuf/compiler/plugin.cc' || echo '$(srcdir)/'`google/protobuf/compiler/plugin.cc - -plugin.pb.lo: google/protobuf/compiler/plugin.pb.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT plugin.pb.lo -MD -MP -MF $(DEPDIR)/plugin.pb.Tpo -c -o plugin.pb.lo `test -f 'google/protobuf/compiler/plugin.pb.cc' || echo '$(srcdir)/'`google/protobuf/compiler/plugin.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/plugin.pb.Tpo $(DEPDIR)/plugin.pb.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/plugin.pb.cc' object='plugin.pb.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o plugin.pb.lo `test -f 'google/protobuf/compiler/plugin.pb.cc' || echo '$(srcdir)/'`google/protobuf/compiler/plugin.pb.cc - -subprocess.lo: google/protobuf/compiler/subprocess.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT subprocess.lo -MD -MP -MF $(DEPDIR)/subprocess.Tpo -c -o subprocess.lo `test -f 'google/protobuf/compiler/subprocess.cc' || echo '$(srcdir)/'`google/protobuf/compiler/subprocess.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/subprocess.Tpo $(DEPDIR)/subprocess.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/subprocess.cc' object='subprocess.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o subprocess.lo `test -f 'google/protobuf/compiler/subprocess.cc' || echo '$(srcdir)/'`google/protobuf/compiler/subprocess.cc - -zip_writer.lo: google/protobuf/compiler/zip_writer.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zip_writer.lo -MD -MP -MF $(DEPDIR)/zip_writer.Tpo -c -o zip_writer.lo `test -f 'google/protobuf/compiler/zip_writer.cc' || echo '$(srcdir)/'`google/protobuf/compiler/zip_writer.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/zip_writer.Tpo $(DEPDIR)/zip_writer.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/zip_writer.cc' object='zip_writer.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zip_writer.lo `test -f 'google/protobuf/compiler/zip_writer.cc' || echo '$(srcdir)/'`google/protobuf/compiler/zip_writer.cc - -cpp_enum.lo: google/protobuf/compiler/cpp/cpp_enum.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cpp_enum.lo -MD -MP -MF $(DEPDIR)/cpp_enum.Tpo -c -o cpp_enum.lo `test -f 'google/protobuf/compiler/cpp/cpp_enum.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_enum.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cpp_enum.Tpo $(DEPDIR)/cpp_enum.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_enum.cc' object='cpp_enum.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cpp_enum.lo `test -f 'google/protobuf/compiler/cpp/cpp_enum.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_enum.cc - -cpp_enum_field.lo: google/protobuf/compiler/cpp/cpp_enum_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cpp_enum_field.lo -MD -MP -MF $(DEPDIR)/cpp_enum_field.Tpo -c -o cpp_enum_field.lo `test -f 'google/protobuf/compiler/cpp/cpp_enum_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_enum_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cpp_enum_field.Tpo $(DEPDIR)/cpp_enum_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_enum_field.cc' object='cpp_enum_field.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cpp_enum_field.lo `test -f 'google/protobuf/compiler/cpp/cpp_enum_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_enum_field.cc - -cpp_extension.lo: google/protobuf/compiler/cpp/cpp_extension.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cpp_extension.lo -MD -MP -MF $(DEPDIR)/cpp_extension.Tpo -c -o cpp_extension.lo `test -f 'google/protobuf/compiler/cpp/cpp_extension.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_extension.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cpp_extension.Tpo $(DEPDIR)/cpp_extension.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_extension.cc' object='cpp_extension.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cpp_extension.lo `test -f 'google/protobuf/compiler/cpp/cpp_extension.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_extension.cc - -cpp_field.lo: google/protobuf/compiler/cpp/cpp_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cpp_field.lo -MD -MP -MF $(DEPDIR)/cpp_field.Tpo -c -o cpp_field.lo `test -f 'google/protobuf/compiler/cpp/cpp_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cpp_field.Tpo $(DEPDIR)/cpp_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_field.cc' object='cpp_field.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cpp_field.lo `test -f 'google/protobuf/compiler/cpp/cpp_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_field.cc - -cpp_file.lo: google/protobuf/compiler/cpp/cpp_file.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cpp_file.lo -MD -MP -MF $(DEPDIR)/cpp_file.Tpo -c -o cpp_file.lo `test -f 'google/protobuf/compiler/cpp/cpp_file.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_file.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cpp_file.Tpo $(DEPDIR)/cpp_file.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_file.cc' object='cpp_file.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cpp_file.lo `test -f 'google/protobuf/compiler/cpp/cpp_file.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_file.cc - -cpp_generator.lo: google/protobuf/compiler/cpp/cpp_generator.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cpp_generator.lo -MD -MP -MF $(DEPDIR)/cpp_generator.Tpo -c -o cpp_generator.lo `test -f 'google/protobuf/compiler/cpp/cpp_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_generator.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cpp_generator.Tpo $(DEPDIR)/cpp_generator.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_generator.cc' object='cpp_generator.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cpp_generator.lo `test -f 'google/protobuf/compiler/cpp/cpp_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_generator.cc - -cpp_helpers.lo: google/protobuf/compiler/cpp/cpp_helpers.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cpp_helpers.lo -MD -MP -MF $(DEPDIR)/cpp_helpers.Tpo -c -o cpp_helpers.lo `test -f 'google/protobuf/compiler/cpp/cpp_helpers.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_helpers.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cpp_helpers.Tpo $(DEPDIR)/cpp_helpers.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_helpers.cc' object='cpp_helpers.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cpp_helpers.lo `test -f 'google/protobuf/compiler/cpp/cpp_helpers.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_helpers.cc - -cpp_message.lo: google/protobuf/compiler/cpp/cpp_message.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cpp_message.lo -MD -MP -MF $(DEPDIR)/cpp_message.Tpo -c -o cpp_message.lo `test -f 'google/protobuf/compiler/cpp/cpp_message.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_message.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cpp_message.Tpo $(DEPDIR)/cpp_message.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_message.cc' object='cpp_message.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cpp_message.lo `test -f 'google/protobuf/compiler/cpp/cpp_message.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_message.cc - -cpp_message_field.lo: google/protobuf/compiler/cpp/cpp_message_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cpp_message_field.lo -MD -MP -MF $(DEPDIR)/cpp_message_field.Tpo -c -o cpp_message_field.lo `test -f 'google/protobuf/compiler/cpp/cpp_message_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_message_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cpp_message_field.Tpo $(DEPDIR)/cpp_message_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_message_field.cc' object='cpp_message_field.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cpp_message_field.lo `test -f 'google/protobuf/compiler/cpp/cpp_message_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_message_field.cc - -cpp_primitive_field.lo: google/protobuf/compiler/cpp/cpp_primitive_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cpp_primitive_field.lo -MD -MP -MF $(DEPDIR)/cpp_primitive_field.Tpo -c -o cpp_primitive_field.lo `test -f 'google/protobuf/compiler/cpp/cpp_primitive_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_primitive_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cpp_primitive_field.Tpo $(DEPDIR)/cpp_primitive_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_primitive_field.cc' object='cpp_primitive_field.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cpp_primitive_field.lo `test -f 'google/protobuf/compiler/cpp/cpp_primitive_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_primitive_field.cc - -cpp_service.lo: google/protobuf/compiler/cpp/cpp_service.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cpp_service.lo -MD -MP -MF $(DEPDIR)/cpp_service.Tpo -c -o cpp_service.lo `test -f 'google/protobuf/compiler/cpp/cpp_service.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_service.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cpp_service.Tpo $(DEPDIR)/cpp_service.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_service.cc' object='cpp_service.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cpp_service.lo `test -f 'google/protobuf/compiler/cpp/cpp_service.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_service.cc - -cpp_string_field.lo: google/protobuf/compiler/cpp/cpp_string_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cpp_string_field.lo -MD -MP -MF $(DEPDIR)/cpp_string_field.Tpo -c -o cpp_string_field.lo `test -f 'google/protobuf/compiler/cpp/cpp_string_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_string_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cpp_string_field.Tpo $(DEPDIR)/cpp_string_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_string_field.cc' object='cpp_string_field.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cpp_string_field.lo `test -f 'google/protobuf/compiler/cpp/cpp_string_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_string_field.cc - -java_enum.lo: google/protobuf/compiler/java/java_enum.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT java_enum.lo -MD -MP -MF $(DEPDIR)/java_enum.Tpo -c -o java_enum.lo `test -f 'google/protobuf/compiler/java/java_enum.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_enum.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/java_enum.Tpo $(DEPDIR)/java_enum.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_enum.cc' object='java_enum.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o java_enum.lo `test -f 'google/protobuf/compiler/java/java_enum.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_enum.cc - -java_enum_field.lo: google/protobuf/compiler/java/java_enum_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT java_enum_field.lo -MD -MP -MF $(DEPDIR)/java_enum_field.Tpo -c -o java_enum_field.lo `test -f 'google/protobuf/compiler/java/java_enum_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_enum_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/java_enum_field.Tpo $(DEPDIR)/java_enum_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_enum_field.cc' object='java_enum_field.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o java_enum_field.lo `test -f 'google/protobuf/compiler/java/java_enum_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_enum_field.cc - -java_extension.lo: google/protobuf/compiler/java/java_extension.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT java_extension.lo -MD -MP -MF $(DEPDIR)/java_extension.Tpo -c -o java_extension.lo `test -f 'google/protobuf/compiler/java/java_extension.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_extension.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/java_extension.Tpo $(DEPDIR)/java_extension.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_extension.cc' object='java_extension.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o java_extension.lo `test -f 'google/protobuf/compiler/java/java_extension.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_extension.cc - -java_field.lo: google/protobuf/compiler/java/java_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT java_field.lo -MD -MP -MF $(DEPDIR)/java_field.Tpo -c -o java_field.lo `test -f 'google/protobuf/compiler/java/java_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/java_field.Tpo $(DEPDIR)/java_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_field.cc' object='java_field.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o java_field.lo `test -f 'google/protobuf/compiler/java/java_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_field.cc - -java_file.lo: google/protobuf/compiler/java/java_file.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT java_file.lo -MD -MP -MF $(DEPDIR)/java_file.Tpo -c -o java_file.lo `test -f 'google/protobuf/compiler/java/java_file.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_file.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/java_file.Tpo $(DEPDIR)/java_file.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_file.cc' object='java_file.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o java_file.lo `test -f 'google/protobuf/compiler/java/java_file.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_file.cc - -java_generator.lo: google/protobuf/compiler/java/java_generator.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT java_generator.lo -MD -MP -MF $(DEPDIR)/java_generator.Tpo -c -o java_generator.lo `test -f 'google/protobuf/compiler/java/java_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_generator.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/java_generator.Tpo $(DEPDIR)/java_generator.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_generator.cc' object='java_generator.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o java_generator.lo `test -f 'google/protobuf/compiler/java/java_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_generator.cc - -java_helpers.lo: google/protobuf/compiler/java/java_helpers.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT java_helpers.lo -MD -MP -MF $(DEPDIR)/java_helpers.Tpo -c -o java_helpers.lo `test -f 'google/protobuf/compiler/java/java_helpers.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_helpers.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/java_helpers.Tpo $(DEPDIR)/java_helpers.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_helpers.cc' object='java_helpers.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o java_helpers.lo `test -f 'google/protobuf/compiler/java/java_helpers.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_helpers.cc - -java_message.lo: google/protobuf/compiler/java/java_message.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT java_message.lo -MD -MP -MF $(DEPDIR)/java_message.Tpo -c -o java_message.lo `test -f 'google/protobuf/compiler/java/java_message.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_message.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/java_message.Tpo $(DEPDIR)/java_message.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_message.cc' object='java_message.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o java_message.lo `test -f 'google/protobuf/compiler/java/java_message.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_message.cc - -java_message_field.lo: google/protobuf/compiler/java/java_message_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT java_message_field.lo -MD -MP -MF $(DEPDIR)/java_message_field.Tpo -c -o java_message_field.lo `test -f 'google/protobuf/compiler/java/java_message_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_message_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/java_message_field.Tpo $(DEPDIR)/java_message_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_message_field.cc' object='java_message_field.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o java_message_field.lo `test -f 'google/protobuf/compiler/java/java_message_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_message_field.cc - -java_primitive_field.lo: google/protobuf/compiler/java/java_primitive_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT java_primitive_field.lo -MD -MP -MF $(DEPDIR)/java_primitive_field.Tpo -c -o java_primitive_field.lo `test -f 'google/protobuf/compiler/java/java_primitive_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_primitive_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/java_primitive_field.Tpo $(DEPDIR)/java_primitive_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_primitive_field.cc' object='java_primitive_field.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o java_primitive_field.lo `test -f 'google/protobuf/compiler/java/java_primitive_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_primitive_field.cc - -java_service.lo: google/protobuf/compiler/java/java_service.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT java_service.lo -MD -MP -MF $(DEPDIR)/java_service.Tpo -c -o java_service.lo `test -f 'google/protobuf/compiler/java/java_service.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_service.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/java_service.Tpo $(DEPDIR)/java_service.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_service.cc' object='java_service.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o java_service.lo `test -f 'google/protobuf/compiler/java/java_service.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_service.cc - -javamicro_enum.lo: google/protobuf/compiler/javamicro/javamicro_enum.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_enum.lo -MD -MP -MF $(DEPDIR)/javamicro_enum.Tpo -c -o javamicro_enum.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_enum.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_enum.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javamicro_enum.Tpo $(DEPDIR)/javamicro_enum.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_enum.cc' object='javamicro_enum.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_enum.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_enum.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_enum.cc - -javamicro_enum_field.lo: google/protobuf/compiler/javamicro/javamicro_enum_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_enum_field.lo -MD -MP -MF $(DEPDIR)/javamicro_enum_field.Tpo -c -o javamicro_enum_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_enum_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_enum_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javamicro_enum_field.Tpo $(DEPDIR)/javamicro_enum_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_enum_field.cc' object='javamicro_enum_field.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_enum_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_enum_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_enum_field.cc - -javamicro_field.lo: google/protobuf/compiler/javamicro/javamicro_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_field.lo -MD -MP -MF $(DEPDIR)/javamicro_field.Tpo -c -o javamicro_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javamicro_field.Tpo $(DEPDIR)/javamicro_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_field.cc' object='javamicro_field.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_field.cc - -javamicro_file.lo: google/protobuf/compiler/javamicro/javamicro_file.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_file.lo -MD -MP -MF $(DEPDIR)/javamicro_file.Tpo -c -o javamicro_file.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_file.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_file.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javamicro_file.Tpo $(DEPDIR)/javamicro_file.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_file.cc' object='javamicro_file.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_file.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_file.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_file.cc - -javamicro_generator.lo: google/protobuf/compiler/javamicro/javamicro_generator.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_generator.lo -MD -MP -MF $(DEPDIR)/javamicro_generator.Tpo -c -o javamicro_generator.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_generator.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javamicro_generator.Tpo $(DEPDIR)/javamicro_generator.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_generator.cc' object='javamicro_generator.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_generator.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_generator.cc - -javamicro_helpers.lo: google/protobuf/compiler/javamicro/javamicro_helpers.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_helpers.lo -MD -MP -MF $(DEPDIR)/javamicro_helpers.Tpo -c -o javamicro_helpers.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_helpers.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_helpers.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javamicro_helpers.Tpo $(DEPDIR)/javamicro_helpers.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_helpers.cc' object='javamicro_helpers.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_helpers.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_helpers.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_helpers.cc - -javamicro_message.lo: google/protobuf/compiler/javamicro/javamicro_message.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_message.lo -MD -MP -MF $(DEPDIR)/javamicro_message.Tpo -c -o javamicro_message.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_message.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_message.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javamicro_message.Tpo $(DEPDIR)/javamicro_message.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_message.cc' object='javamicro_message.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.o: google/protobuf/compiler/cpp/cpp_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.o -MD -MP -MF google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Tpo -c -o google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Tpo google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_unittest.cc' object='google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_message.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_message.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_message.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_unittest.cc -javamicro_message_field.lo: google/protobuf/compiler/javamicro/javamicro_message_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_message_field.lo -MD -MP -MF $(DEPDIR)/javamicro_message_field.Tpo -c -o javamicro_message_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_message_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_message_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javamicro_message_field.Tpo $(DEPDIR)/javamicro_message_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_message_field.cc' object='javamicro_message_field.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.obj: google/protobuf/compiler/cpp/cpp_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.obj -MD -MP -MF google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Tpo -c -o google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Tpo google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_unittest.cc' object='google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_message_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_message_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_message_field.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_unittest.cc'; fi` -javamicro_primitive_field.lo: google/protobuf/compiler/javamicro/javamicro_primitive_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_primitive_field.lo -MD -MP -MF $(DEPDIR)/javamicro_primitive_field.Tpo -c -o javamicro_primitive_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_primitive_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_primitive_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javamicro_primitive_field.Tpo $(DEPDIR)/javamicro_primitive_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_primitive_field.cc' object='javamicro_primitive_field.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-test_util.o: google/protobuf/test_util.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-test_util.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-test_util.o `test -f 'google/protobuf/test_util.cc' || echo '$(srcdir)/'`google/protobuf/test_util.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/test_util.cc' object='google/protobuf/protobuf_lazy_descriptor_test-test_util.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_primitive_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_primitive_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_primitive_field.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-test_util.o `test -f 'google/protobuf/test_util.cc' || echo '$(srcdir)/'`google/protobuf/test_util.cc -javanano_enum.lo: google/protobuf/compiler/javanano/javanano_enum.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javanano_enum.lo -MD -MP -MF $(DEPDIR)/javanano_enum.Tpo -c -o javanano_enum.lo `test -f 'google/protobuf/compiler/javanano/javanano_enum.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_enum.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javanano_enum.Tpo $(DEPDIR)/javanano_enum.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javanano/javanano_enum.cc' object='javanano_enum.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-test_util.obj: google/protobuf/test_util.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-test_util.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-test_util.obj `if test -f 'google/protobuf/test_util.cc'; then $(CYGPATH_W) 'google/protobuf/test_util.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/test_util.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/test_util.cc' object='google/protobuf/protobuf_lazy_descriptor_test-test_util.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javanano_enum.lo `test -f 'google/protobuf/compiler/javanano/javanano_enum.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_enum.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-test_util.obj `if test -f 'google/protobuf/test_util.cc'; then $(CYGPATH_W) 'google/protobuf/test_util.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/test_util.cc'; fi` -javanano_enum_field.lo: google/protobuf/compiler/javanano/javanano_enum_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javanano_enum_field.lo -MD -MP -MF $(DEPDIR)/javanano_enum_field.Tpo -c -o javanano_enum_field.lo `test -f 'google/protobuf/compiler/javanano/javanano_enum_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_enum_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javanano_enum_field.Tpo $(DEPDIR)/javanano_enum_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javanano/javanano_enum_field.cc' object='javanano_enum_field.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.o: google/protobuf/testing/googletest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.o -MD -MP -MF google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Tpo -c -o google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.o `test -f 'google/protobuf/testing/googletest.cc' || echo '$(srcdir)/'`google/protobuf/testing/googletest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Tpo google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/googletest.cc' object='google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javanano_enum_field.lo `test -f 'google/protobuf/compiler/javanano/javanano_enum_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_enum_field.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.o `test -f 'google/protobuf/testing/googletest.cc' || echo '$(srcdir)/'`google/protobuf/testing/googletest.cc -javanano_extension.lo: google/protobuf/compiler/javanano/javanano_extension.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javanano_extension.lo -MD -MP -MF $(DEPDIR)/javanano_extension.Tpo -c -o javanano_extension.lo `test -f 'google/protobuf/compiler/javanano/javanano_extension.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_extension.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javanano_extension.Tpo $(DEPDIR)/javanano_extension.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javanano/javanano_extension.cc' object='javanano_extension.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.obj: google/protobuf/testing/googletest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.obj -MD -MP -MF google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Tpo -c -o google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.obj `if test -f 'google/protobuf/testing/googletest.cc'; then $(CYGPATH_W) 'google/protobuf/testing/googletest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/googletest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Tpo google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/googletest.cc' object='google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javanano_extension.lo `test -f 'google/protobuf/compiler/javanano/javanano_extension.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_extension.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/testing/protobuf_lazy_descriptor_test-googletest.obj `if test -f 'google/protobuf/testing/googletest.cc'; then $(CYGPATH_W) 'google/protobuf/testing/googletest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/googletest.cc'; fi` -javanano_field.lo: google/protobuf/compiler/javanano/javanano_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javanano_field.lo -MD -MP -MF $(DEPDIR)/javanano_field.Tpo -c -o javanano_field.lo `test -f 'google/protobuf/compiler/javanano/javanano_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javanano_field.Tpo $(DEPDIR)/javanano_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javanano/javanano_field.cc' object='javanano_field.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/testing/protobuf_lazy_descriptor_test-file.o: google/protobuf/testing/file.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/testing/protobuf_lazy_descriptor_test-file.o -MD -MP -MF google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-file.Tpo -c -o google/protobuf/testing/protobuf_lazy_descriptor_test-file.o `test -f 'google/protobuf/testing/file.cc' || echo '$(srcdir)/'`google/protobuf/testing/file.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-file.Tpo google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-file.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/file.cc' object='google/protobuf/testing/protobuf_lazy_descriptor_test-file.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javanano_field.lo `test -f 'google/protobuf/compiler/javanano/javanano_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_field.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/testing/protobuf_lazy_descriptor_test-file.o `test -f 'google/protobuf/testing/file.cc' || echo '$(srcdir)/'`google/protobuf/testing/file.cc -javanano_file.lo: google/protobuf/compiler/javanano/javanano_file.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javanano_file.lo -MD -MP -MF $(DEPDIR)/javanano_file.Tpo -c -o javanano_file.lo `test -f 'google/protobuf/compiler/javanano/javanano_file.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_file.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javanano_file.Tpo $(DEPDIR)/javanano_file.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javanano/javanano_file.cc' object='javanano_file.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/testing/protobuf_lazy_descriptor_test-file.obj: google/protobuf/testing/file.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/testing/protobuf_lazy_descriptor_test-file.obj -MD -MP -MF google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-file.Tpo -c -o google/protobuf/testing/protobuf_lazy_descriptor_test-file.obj `if test -f 'google/protobuf/testing/file.cc'; then $(CYGPATH_W) 'google/protobuf/testing/file.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/file.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-file.Tpo google/protobuf/testing/$(DEPDIR)/protobuf_lazy_descriptor_test-file.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/file.cc' object='google/protobuf/testing/protobuf_lazy_descriptor_test-file.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javanano_file.lo `test -f 'google/protobuf/compiler/javanano/javanano_file.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_file.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/testing/protobuf_lazy_descriptor_test-file.obj `if test -f 'google/protobuf/testing/file.cc'; then $(CYGPATH_W) 'google/protobuf/testing/file.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/file.cc'; fi` -javanano_generator.lo: google/protobuf/compiler/javanano/javanano_generator.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javanano_generator.lo -MD -MP -MF $(DEPDIR)/javanano_generator.Tpo -c -o javanano_generator.lo `test -f 'google/protobuf/compiler/javanano/javanano_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_generator.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javanano_generator.Tpo $(DEPDIR)/javanano_generator.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javanano/javanano_generator.cc' object='javanano_generator.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.o: google/protobuf/unittest_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.o `test -f 'google/protobuf/unittest_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javanano_generator.lo `test -f 'google/protobuf/compiler/javanano/javanano_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_generator.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.o `test -f 'google/protobuf/unittest_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite.pb.cc -javanano_helpers.lo: google/protobuf/compiler/javanano/javanano_helpers.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javanano_helpers.lo -MD -MP -MF $(DEPDIR)/javanano_helpers.Tpo -c -o javanano_helpers.lo `test -f 'google/protobuf/compiler/javanano/javanano_helpers.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_helpers.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javanano_helpers.Tpo $(DEPDIR)/javanano_helpers.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javanano/javanano_helpers.cc' object='javanano_helpers.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.obj: google/protobuf/unittest_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.obj `if test -f 'google/protobuf/unittest_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javanano_helpers.lo `test -f 'google/protobuf/compiler/javanano/javanano_helpers.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_helpers.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_lite.pb.obj `if test -f 'google/protobuf/unittest_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite.pb.cc'; fi` -javanano_message.lo: google/protobuf/compiler/javanano/javanano_message.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javanano_message.lo -MD -MP -MF $(DEPDIR)/javanano_message.Tpo -c -o javanano_message.lo `test -f 'google/protobuf/compiler/javanano/javanano_message.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_message.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javanano_message.Tpo $(DEPDIR)/javanano_message.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javanano/javanano_message.cc' object='javanano_message.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.o: google/protobuf/unittest_import_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.o `test -f 'google/protobuf/unittest_import_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_lite.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_lite.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javanano_message.lo `test -f 'google/protobuf/compiler/javanano/javanano_message.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_message.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.o `test -f 'google/protobuf/unittest_import_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_lite.pb.cc -javanano_message_field.lo: google/protobuf/compiler/javanano/javanano_message_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javanano_message_field.lo -MD -MP -MF $(DEPDIR)/javanano_message_field.Tpo -c -o javanano_message_field.lo `test -f 'google/protobuf/compiler/javanano/javanano_message_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_message_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javanano_message_field.Tpo $(DEPDIR)/javanano_message_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javanano/javanano_message_field.cc' object='javanano_message_field.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.obj: google/protobuf/unittest_import_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.obj `if test -f 'google/protobuf/unittest_import_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_lite.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_lite.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javanano_message_field.lo `test -f 'google/protobuf/compiler/javanano/javanano_message_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_message_field.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import_lite.pb.obj `if test -f 'google/protobuf/unittest_import_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_lite.pb.cc'; fi` -javanano_primitive_field.lo: google/protobuf/compiler/javanano/javanano_primitive_field.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javanano_primitive_field.lo -MD -MP -MF $(DEPDIR)/javanano_primitive_field.Tpo -c -o javanano_primitive_field.lo `test -f 'google/protobuf/compiler/javanano/javanano_primitive_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_primitive_field.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/javanano_primitive_field.Tpo $(DEPDIR)/javanano_primitive_field.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javanano/javanano_primitive_field.cc' object='javanano_primitive_field.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.o: google/protobuf/unittest_import_public_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.o `test -f 'google/protobuf/unittest_import_public_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_public_lite.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_public_lite.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javanano_primitive_field.lo `test -f 'google/protobuf/compiler/javanano/javanano_primitive_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javanano/javanano_primitive_field.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.o `test -f 'google/protobuf/unittest_import_public_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_public_lite.pb.cc -python_generator.lo: google/protobuf/compiler/python/python_generator.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT python_generator.lo -MD -MP -MF $(DEPDIR)/python_generator.Tpo -c -o python_generator.lo `test -f 'google/protobuf/compiler/python/python_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/python/python_generator.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/python_generator.Tpo $(DEPDIR)/python_generator.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/python/python_generator.cc' object='python_generator.lo' libtool=yes @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.obj: google/protobuf/unittest_import_public_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.obj `if test -f 'google/protobuf/unittest_import_public_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_public_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_public_lite.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_public_lite.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o python_generator.lo `test -f 'google/protobuf/compiler/python/python_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/python/python_generator.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public_lite.pb.obj `if test -f 'google/protobuf/unittest_import_public_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_public_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_public_lite.pb.cc'; fi` -protobuf_lazy_descriptor_test-cpp_unittest.o: google/protobuf/compiler/cpp/cpp_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-cpp_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Tpo -c -o protobuf_lazy_descriptor_test-cpp_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_unittest.cc' object='protobuf_lazy_descriptor_test-cpp_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.o: google/protobuf/unittest.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.o `test -f 'google/protobuf/unittest.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-cpp_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.o `test -f 'google/protobuf/unittest.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest.pb.cc -protobuf_lazy_descriptor_test-cpp_unittest.obj: google/protobuf/compiler/cpp/cpp_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-cpp_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Tpo -c -o protobuf_lazy_descriptor_test-cpp_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-cpp_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_unittest.cc' object='protobuf_lazy_descriptor_test-cpp_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.obj: google/protobuf/unittest.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.obj `if test -f 'google/protobuf/unittest.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-cpp_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest.pb.obj `if test -f 'google/protobuf/unittest.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest.pb.cc'; fi` -protobuf_lazy_descriptor_test-test_util.o: google/protobuf/test_util.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-test_util.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Tpo -c -o protobuf_lazy_descriptor_test-test_util.o `test -f 'google/protobuf/test_util.cc' || echo '$(srcdir)/'`google/protobuf/test_util.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/test_util.cc' object='protobuf_lazy_descriptor_test-test_util.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.o: google/protobuf/unittest_empty.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.o `test -f 'google/protobuf/unittest_empty.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_empty.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_empty.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-test_util.o `test -f 'google/protobuf/test_util.cc' || echo '$(srcdir)/'`google/protobuf/test_util.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.o `test -f 'google/protobuf/unittest_empty.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_empty.pb.cc -protobuf_lazy_descriptor_test-test_util.obj: google/protobuf/test_util.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-test_util.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Tpo -c -o protobuf_lazy_descriptor_test-test_util.obj `if test -f 'google/protobuf/test_util.cc'; then $(CYGPATH_W) 'google/protobuf/test_util.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/test_util.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-test_util.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/test_util.cc' object='protobuf_lazy_descriptor_test-test_util.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.obj: google/protobuf/unittest_empty.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.obj `if test -f 'google/protobuf/unittest_empty.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_empty.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_empty.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_empty.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-test_util.obj `if test -f 'google/protobuf/test_util.cc'; then $(CYGPATH_W) 'google/protobuf/test_util.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/test_util.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_empty.pb.obj `if test -f 'google/protobuf/unittest_empty.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_empty.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_empty.pb.cc'; fi` -protobuf_lazy_descriptor_test-googletest.o: google/protobuf/testing/googletest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-googletest.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Tpo -c -o protobuf_lazy_descriptor_test-googletest.o `test -f 'google/protobuf/testing/googletest.cc' || echo '$(srcdir)/'`google/protobuf/testing/googletest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/googletest.cc' object='protobuf_lazy_descriptor_test-googletest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.o: google/protobuf/unittest_import.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.o `test -f 'google/protobuf/unittest_import.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-googletest.o `test -f 'google/protobuf/testing/googletest.cc' || echo '$(srcdir)/'`google/protobuf/testing/googletest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.o `test -f 'google/protobuf/unittest_import.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import.pb.cc -protobuf_lazy_descriptor_test-googletest.obj: google/protobuf/testing/googletest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-googletest.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Tpo -c -o protobuf_lazy_descriptor_test-googletest.obj `if test -f 'google/protobuf/testing/googletest.cc'; then $(CYGPATH_W) 'google/protobuf/testing/googletest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/googletest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-googletest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/googletest.cc' object='protobuf_lazy_descriptor_test-googletest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.obj: google/protobuf/unittest_import.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.obj `if test -f 'google/protobuf/unittest_import.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-googletest.obj `if test -f 'google/protobuf/testing/googletest.cc'; then $(CYGPATH_W) 'google/protobuf/testing/googletest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/googletest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import.pb.obj `if test -f 'google/protobuf/unittest_import.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import.pb.cc'; fi` -protobuf_lazy_descriptor_test-file.o: google/protobuf/testing/file.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-file.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-file.Tpo -c -o protobuf_lazy_descriptor_test-file.o `test -f 'google/protobuf/testing/file.cc' || echo '$(srcdir)/'`google/protobuf/testing/file.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-file.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-file.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/file.cc' object='protobuf_lazy_descriptor_test-file.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.o: google/protobuf/unittest_import_public.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.o `test -f 'google/protobuf/unittest_import_public.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_public.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_public.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-file.o `test -f 'google/protobuf/testing/file.cc' || echo '$(srcdir)/'`google/protobuf/testing/file.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.o `test -f 'google/protobuf/unittest_import_public.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_public.pb.cc -protobuf_lazy_descriptor_test-file.obj: google/protobuf/testing/file.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-file.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-file.Tpo -c -o protobuf_lazy_descriptor_test-file.obj `if test -f 'google/protobuf/testing/file.cc'; then $(CYGPATH_W) 'google/protobuf/testing/file.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/file.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-file.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-file.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/file.cc' object='protobuf_lazy_descriptor_test-file.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.obj: google/protobuf/unittest_import_public.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.obj `if test -f 'google/protobuf/unittest_import_public.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_public.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_public.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_public.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_public.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-file.obj `if test -f 'google/protobuf/testing/file.cc'; then $(CYGPATH_W) 'google/protobuf/testing/file.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/file.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_import_public.pb.obj `if test -f 'google/protobuf/unittest_import_public.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_public.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_public.pb.cc'; fi` -protobuf_lazy_descriptor_test-unittest_lite.pb.o: google/protobuf/unittest_lite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_lite.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_lite.pb.o `test -f 'google/protobuf/unittest_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite.pb.cc' object='protobuf_lazy_descriptor_test-unittest_lite.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.o: google/protobuf/unittest_mset.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.o `test -f 'google/protobuf/unittest_mset.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_mset.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_mset.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_lite.pb.o `test -f 'google/protobuf/unittest_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.o `test -f 'google/protobuf/unittest_mset.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_mset.pb.cc -protobuf_lazy_descriptor_test-unittest_lite.pb.obj: google/protobuf/unittest_lite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_lite.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_lite.pb.obj `if test -f 'google/protobuf/unittest_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite.pb.cc' object='protobuf_lazy_descriptor_test-unittest_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.obj: google/protobuf/unittest_mset.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.obj `if test -f 'google/protobuf/unittest_mset.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_mset.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_mset.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_mset.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_lite.pb.obj `if test -f 'google/protobuf/unittest_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_mset.pb.obj `if test -f 'google/protobuf/unittest_mset.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_mset.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_mset.pb.cc'; fi` -protobuf_lazy_descriptor_test-unittest_import_lite.pb.o: google/protobuf/unittest_import_lite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_import_lite.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_import_lite.pb.o `test -f 'google/protobuf/unittest_import_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_lite.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_lite.pb.cc' object='protobuf_lazy_descriptor_test-unittest_import_lite.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.o: google/protobuf/unittest_optimize_for.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.o `test -f 'google/protobuf/unittest_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_optimize_for.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_optimize_for.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_import_lite.pb.o `test -f 'google/protobuf/unittest_import_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_lite.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.o `test -f 'google/protobuf/unittest_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_optimize_for.pb.cc -protobuf_lazy_descriptor_test-unittest_import_lite.pb.obj: google/protobuf/unittest_import_lite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_import_lite.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_import_lite.pb.obj `if test -f 'google/protobuf/unittest_import_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_lite.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import_lite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_lite.pb.cc' object='protobuf_lazy_descriptor_test-unittest_import_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.obj: google/protobuf/unittest_optimize_for.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_optimize_for.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_optimize_for.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_import_lite.pb.obj `if test -f 'google/protobuf/unittest_import_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_lite.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_optimize_for.pb.cc'; fi` -protobuf_lazy_descriptor_test-unittest.pb.o: google/protobuf/unittest.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest.pb.o `test -f 'google/protobuf/unittest.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest.pb.cc' object='protobuf_lazy_descriptor_test-unittest.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.o: google/protobuf/unittest_embed_optimize_for.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.o `test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_embed_optimize_for.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_embed_optimize_for.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest.pb.o `test -f 'google/protobuf/unittest.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.o `test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_embed_optimize_for.pb.cc -protobuf_lazy_descriptor_test-unittest.pb.obj: google/protobuf/unittest.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest.pb.obj `if test -f 'google/protobuf/unittest.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest.pb.cc' object='protobuf_lazy_descriptor_test-unittest.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.obj: google/protobuf/unittest_embed_optimize_for.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_embed_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_embed_optimize_for.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_embed_optimize_for.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest.pb.obj `if test -f 'google/protobuf/unittest.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_embed_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_embed_optimize_for.pb.cc'; fi` -protobuf_lazy_descriptor_test-unittest_empty.pb.o: google/protobuf/unittest_empty.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_empty.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_empty.pb.o `test -f 'google/protobuf/unittest_empty.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_empty.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_empty.pb.cc' object='protobuf_lazy_descriptor_test-unittest_empty.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.o: google/protobuf/unittest_custom_options.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.o `test -f 'google/protobuf/unittest_custom_options.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_custom_options.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_custom_options.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_empty.pb.o `test -f 'google/protobuf/unittest_empty.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_empty.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.o `test -f 'google/protobuf/unittest_custom_options.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_custom_options.pb.cc -protobuf_lazy_descriptor_test-unittest_empty.pb.obj: google/protobuf/unittest_empty.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_empty.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_empty.pb.obj `if test -f 'google/protobuf/unittest_empty.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_empty.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_empty.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_empty.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_empty.pb.cc' object='protobuf_lazy_descriptor_test-unittest_empty.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.obj: google/protobuf/unittest_custom_options.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.obj `if test -f 'google/protobuf/unittest_custom_options.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_custom_options.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_custom_options.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_custom_options.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_empty.pb.obj `if test -f 'google/protobuf/unittest_empty.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_empty.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_empty.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_custom_options.pb.obj `if test -f 'google/protobuf/unittest_custom_options.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_custom_options.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_custom_options.pb.cc'; fi` -protobuf_lazy_descriptor_test-unittest_import.pb.o: google/protobuf/unittest_import.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_import.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_import.pb.o `test -f 'google/protobuf/unittest_import.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import.pb.cc' object='protobuf_lazy_descriptor_test-unittest_import.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.o: google/protobuf/unittest_lite_imports_nonlite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.o `test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite_imports_nonlite.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite_imports_nonlite.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_import.pb.o `test -f 'google/protobuf/unittest_import.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.o `test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite_imports_nonlite.pb.cc -protobuf_lazy_descriptor_test-unittest_import.pb.obj: google/protobuf/unittest_import.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_import.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_import.pb.obj `if test -f 'google/protobuf/unittest_import.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_import.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import.pb.cc' object='protobuf_lazy_descriptor_test-unittest_import.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.obj: google/protobuf/unittest_lite_imports_nonlite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.obj `if test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite_imports_nonlite.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite_imports_nonlite.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_import.pb.obj `if test -f 'google/protobuf/unittest_import.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.obj `if test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite_imports_nonlite.pb.cc'; fi` -protobuf_lazy_descriptor_test-unittest_mset.pb.o: google/protobuf/unittest_mset.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_mset.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_mset.pb.o `test -f 'google/protobuf/unittest_mset.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_mset.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_mset.pb.cc' object='protobuf_lazy_descriptor_test-unittest_mset.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.o: google/protobuf/unittest_no_generic_services.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.o `test -f 'google/protobuf/unittest_no_generic_services.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_no_generic_services.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_no_generic_services.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_mset.pb.o `test -f 'google/protobuf/unittest_mset.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_mset.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.o `test -f 'google/protobuf/unittest_no_generic_services.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_no_generic_services.pb.cc -protobuf_lazy_descriptor_test-unittest_mset.pb.obj: google/protobuf/unittest_mset.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_mset.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_mset.pb.obj `if test -f 'google/protobuf/unittest_mset.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_mset.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_mset.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_mset.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_mset.pb.cc' object='protobuf_lazy_descriptor_test-unittest_mset.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.obj: google/protobuf/unittest_no_generic_services.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Tpo -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.obj `if test -f 'google/protobuf/unittest_no_generic_services.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_no_generic_services.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_no_generic_services.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_no_generic_services.pb.cc' object='google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_mset.pb.obj `if test -f 'google/protobuf/unittest_mset.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_mset.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_mset.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.obj `if test -f 'google/protobuf/unittest_no_generic_services.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_no_generic_services.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_no_generic_services.pb.cc'; fi` -protobuf_lazy_descriptor_test-unittest_optimize_for.pb.o: google/protobuf/unittest_optimize_for.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_optimize_for.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_optimize_for.pb.o `test -f 'google/protobuf/unittest_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_optimize_for.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_optimize_for.pb.cc' object='protobuf_lazy_descriptor_test-unittest_optimize_for.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.o: google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.o -MD -MP -MF google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Tpo -c -o google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.o `test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Tpo google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' object='google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_optimize_for.pb.o `test -f 'google/protobuf/unittest_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_optimize_for.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.o `test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc -protobuf_lazy_descriptor_test-unittest_optimize_for.pb.obj: google/protobuf/unittest_optimize_for.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_optimize_for.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_optimize_for.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_optimize_for.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_optimize_for.pb.cc' object='protobuf_lazy_descriptor_test-unittest_optimize_for.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.obj: google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.obj -MD -MP -MF google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Tpo -c -o google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.obj `if test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Tpo google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' object='google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_optimize_for.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/cpp/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.obj `if test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; fi` -protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.o: google/protobuf/unittest_embed_optimize_for.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.o `test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_embed_optimize_for.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_embed_optimize_for.pb.cc' object='protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lite_test-lite_unittest.o: google/protobuf/lite_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lite_test-lite_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lite_test-lite_unittest.Tpo -c -o google/protobuf/protobuf_lite_test-lite_unittest.o `test -f 'google/protobuf/lite_unittest.cc' || echo '$(srcdir)/'`google/protobuf/lite_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lite_test-lite_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_lite_test-lite_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/lite_unittest.cc' object='google/protobuf/protobuf_lite_test-lite_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.o `test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_embed_optimize_for.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lite_test-lite_unittest.o `test -f 'google/protobuf/lite_unittest.cc' || echo '$(srcdir)/'`google/protobuf/lite_unittest.cc -protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.obj: google/protobuf/unittest_embed_optimize_for.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_embed_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_embed_optimize_for.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_embed_optimize_for.pb.cc' object='protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lite_test-lite_unittest.obj: google/protobuf/lite_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lite_test-lite_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lite_test-lite_unittest.Tpo -c -o google/protobuf/protobuf_lite_test-lite_unittest.obj `if test -f 'google/protobuf/lite_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/lite_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/lite_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lite_test-lite_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_lite_test-lite_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/lite_unittest.cc' object='google/protobuf/protobuf_lite_test-lite_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_embed_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_embed_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_embed_optimize_for.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lite_test-lite_unittest.obj `if test -f 'google/protobuf/lite_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/lite_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/lite_unittest.cc'; fi` -protobuf_lazy_descriptor_test-unittest_custom_options.pb.o: google/protobuf/unittest_custom_options.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_custom_options.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_custom_options.pb.o `test -f 'google/protobuf/unittest_custom_options.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_custom_options.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_custom_options.pb.cc' object='protobuf_lazy_descriptor_test-unittest_custom_options.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lite_test-test_util_lite.o: google/protobuf/test_util_lite.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lite_test-test_util_lite.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lite_test-test_util_lite.Tpo -c -o google/protobuf/protobuf_lite_test-test_util_lite.o `test -f 'google/protobuf/test_util_lite.cc' || echo '$(srcdir)/'`google/protobuf/test_util_lite.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lite_test-test_util_lite.Tpo google/protobuf/$(DEPDIR)/protobuf_lite_test-test_util_lite.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/test_util_lite.cc' object='google/protobuf/protobuf_lite_test-test_util_lite.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_custom_options.pb.o `test -f 'google/protobuf/unittest_custom_options.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_custom_options.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lite_test-test_util_lite.o `test -f 'google/protobuf/test_util_lite.cc' || echo '$(srcdir)/'`google/protobuf/test_util_lite.cc -protobuf_lazy_descriptor_test-unittest_custom_options.pb.obj: google/protobuf/unittest_custom_options.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_custom_options.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_custom_options.pb.obj `if test -f 'google/protobuf/unittest_custom_options.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_custom_options.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_custom_options.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_custom_options.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_custom_options.pb.cc' object='protobuf_lazy_descriptor_test-unittest_custom_options.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lite_test-test_util_lite.obj: google/protobuf/test_util_lite.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lite_test-test_util_lite.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lite_test-test_util_lite.Tpo -c -o google/protobuf/protobuf_lite_test-test_util_lite.obj `if test -f 'google/protobuf/test_util_lite.cc'; then $(CYGPATH_W) 'google/protobuf/test_util_lite.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/test_util_lite.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lite_test-test_util_lite.Tpo google/protobuf/$(DEPDIR)/protobuf_lite_test-test_util_lite.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/test_util_lite.cc' object='google/protobuf/protobuf_lite_test-test_util_lite.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_custom_options.pb.obj `if test -f 'google/protobuf/unittest_custom_options.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_custom_options.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_custom_options.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lite_test-test_util_lite.obj `if test -f 'google/protobuf/test_util_lite.cc'; then $(CYGPATH_W) 'google/protobuf/test_util_lite.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/test_util_lite.cc'; fi` -protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.o: google/protobuf/unittest_lite_imports_nonlite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.o `test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite_imports_nonlite.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite_imports_nonlite.pb.cc' object='protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lite_test-unittest_lite.pb.o: google/protobuf/unittest_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lite_test-unittest_lite.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Tpo -c -o google/protobuf/protobuf_lite_test-unittest_lite.pb.o `test -f 'google/protobuf/unittest_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite.pb.cc' object='google/protobuf/protobuf_lite_test-unittest_lite.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.o `test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite_imports_nonlite.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lite_test-unittest_lite.pb.o `test -f 'google/protobuf/unittest_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite.pb.cc -protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.obj: google/protobuf/unittest_lite_imports_nonlite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.obj `if test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite_imports_nonlite.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite_imports_nonlite.pb.cc' object='protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lite_test-unittest_lite.pb.obj: google/protobuf/unittest_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lite_test-unittest_lite.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Tpo -c -o google/protobuf/protobuf_lite_test-unittest_lite.pb.obj `if test -f 'google/protobuf/unittest_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite.pb.cc' object='google/protobuf/protobuf_lite_test-unittest_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_lite_imports_nonlite.pb.obj `if test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite_imports_nonlite.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lite_test-unittest_lite.pb.obj `if test -f 'google/protobuf/unittest_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite.pb.cc'; fi` -protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.o: google/protobuf/unittest_no_generic_services.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.o `test -f 'google/protobuf/unittest_no_generic_services.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_no_generic_services.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_no_generic_services.pb.cc' object='protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lite_test-unittest_import_lite.pb.o: google/protobuf/unittest_import_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lite_test-unittest_import_lite.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Tpo -c -o google/protobuf/protobuf_lite_test-unittest_import_lite.pb.o `test -f 'google/protobuf/unittest_import_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_lite.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_lite.pb.cc' object='google/protobuf/protobuf_lite_test-unittest_import_lite.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.o `test -f 'google/protobuf/unittest_no_generic_services.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_no_generic_services.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lite_test-unittest_import_lite.pb.o `test -f 'google/protobuf/unittest_import_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_lite.pb.cc -protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.obj: google/protobuf/unittest_no_generic_services.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Tpo -c -o protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.obj `if test -f 'google/protobuf/unittest_no_generic_services.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_no_generic_services.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_no_generic_services.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_no_generic_services.pb.cc' object='protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lite_test-unittest_import_lite.pb.obj: google/protobuf/unittest_import_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lite_test-unittest_import_lite.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Tpo -c -o google/protobuf/protobuf_lite_test-unittest_import_lite.pb.obj `if test -f 'google/protobuf/unittest_import_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_lite.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_lite.pb.cc' object='google/protobuf/protobuf_lite_test-unittest_import_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-unittest_no_generic_services.pb.obj `if test -f 'google/protobuf/unittest_no_generic_services.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_no_generic_services.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_no_generic_services.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lite_test-unittest_import_lite.pb.obj `if test -f 'google/protobuf/unittest_import_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_lite.pb.cc'; fi` -protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.o: google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Tpo -c -o protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.o `test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' object='protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.o: google/protobuf/unittest_import_public_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_public_lite.pb.Tpo -c -o google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.o `test -f 'google/protobuf/unittest_import_public_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_public_lite.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_public_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_public_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_public_lite.pb.cc' object='google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.o `test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.o `test -f 'google/protobuf/unittest_import_public_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_public_lite.pb.cc -protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.obj: google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Tpo -c -o protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.obj `if test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Tpo $(DEPDIR)/protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' object='protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.obj: google/protobuf/unittest_import_public_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_public_lite.pb.Tpo -c -o google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.obj `if test -f 'google/protobuf/unittest_import_public_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_public_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_public_lite.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_public_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_lite_test-unittest_import_public_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_public_lite.pb.cc' object='google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_lazy_descriptor_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_lazy_descriptor_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lazy_descriptor_test-cpp_test_bad_identifiers.pb.obj `if test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_lite_test-unittest_import_public_lite.pb.obj `if test -f 'google/protobuf/unittest_import_public_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_public_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_public_lite.pb.cc'; fi` -protobuf_lite_test-lite_unittest.o: google/protobuf/lite_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lite_test-lite_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_lite_test-lite_unittest.Tpo -c -o protobuf_lite_test-lite_unittest.o `test -f 'google/protobuf/lite_unittest.cc' || echo '$(srcdir)/'`google/protobuf/lite_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lite_test-lite_unittest.Tpo $(DEPDIR)/protobuf_lite_test-lite_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/lite_unittest.cc' object='protobuf_lite_test-lite_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-common_unittest.o: google/protobuf/stubs/common_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-common_unittest.o -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-common_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-common_unittest.o `test -f 'google/protobuf/stubs/common_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/common_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-common_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-common_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/common_unittest.cc' object='google/protobuf/stubs/protobuf_test-common_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lite_test-lite_unittest.o `test -f 'google/protobuf/lite_unittest.cc' || echo '$(srcdir)/'`google/protobuf/lite_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-common_unittest.o `test -f 'google/protobuf/stubs/common_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/common_unittest.cc -protobuf_lite_test-lite_unittest.obj: google/protobuf/lite_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lite_test-lite_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_lite_test-lite_unittest.Tpo -c -o protobuf_lite_test-lite_unittest.obj `if test -f 'google/protobuf/lite_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/lite_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/lite_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lite_test-lite_unittest.Tpo $(DEPDIR)/protobuf_lite_test-lite_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/lite_unittest.cc' object='protobuf_lite_test-lite_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-common_unittest.obj: google/protobuf/stubs/common_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-common_unittest.obj -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-common_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-common_unittest.obj `if test -f 'google/protobuf/stubs/common_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/common_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/common_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-common_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-common_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/common_unittest.cc' object='google/protobuf/stubs/protobuf_test-common_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lite_test-lite_unittest.obj `if test -f 'google/protobuf/lite_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/lite_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/lite_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-common_unittest.obj `if test -f 'google/protobuf/stubs/common_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/common_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/common_unittest.cc'; fi` -protobuf_lite_test-test_util_lite.o: google/protobuf/test_util_lite.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lite_test-test_util_lite.o -MD -MP -MF $(DEPDIR)/protobuf_lite_test-test_util_lite.Tpo -c -o protobuf_lite_test-test_util_lite.o `test -f 'google/protobuf/test_util_lite.cc' || echo '$(srcdir)/'`google/protobuf/test_util_lite.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lite_test-test_util_lite.Tpo $(DEPDIR)/protobuf_lite_test-test_util_lite.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/test_util_lite.cc' object='protobuf_lite_test-test_util_lite.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-once_unittest.o: google/protobuf/stubs/once_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-once_unittest.o -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-once_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-once_unittest.o `test -f 'google/protobuf/stubs/once_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/once_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-once_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-once_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/once_unittest.cc' object='google/protobuf/stubs/protobuf_test-once_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lite_test-test_util_lite.o `test -f 'google/protobuf/test_util_lite.cc' || echo '$(srcdir)/'`google/protobuf/test_util_lite.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-once_unittest.o `test -f 'google/protobuf/stubs/once_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/once_unittest.cc -protobuf_lite_test-test_util_lite.obj: google/protobuf/test_util_lite.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lite_test-test_util_lite.obj -MD -MP -MF $(DEPDIR)/protobuf_lite_test-test_util_lite.Tpo -c -o protobuf_lite_test-test_util_lite.obj `if test -f 'google/protobuf/test_util_lite.cc'; then $(CYGPATH_W) 'google/protobuf/test_util_lite.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/test_util_lite.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lite_test-test_util_lite.Tpo $(DEPDIR)/protobuf_lite_test-test_util_lite.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/test_util_lite.cc' object='protobuf_lite_test-test_util_lite.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-once_unittest.obj: google/protobuf/stubs/once_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-once_unittest.obj -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-once_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-once_unittest.obj `if test -f 'google/protobuf/stubs/once_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/once_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/once_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-once_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-once_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/once_unittest.cc' object='google/protobuf/stubs/protobuf_test-once_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lite_test-test_util_lite.obj `if test -f 'google/protobuf/test_util_lite.cc'; then $(CYGPATH_W) 'google/protobuf/test_util_lite.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/test_util_lite.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-once_unittest.obj `if test -f 'google/protobuf/stubs/once_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/once_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/once_unittest.cc'; fi` -protobuf_lite_test-unittest_lite.pb.o: google/protobuf/unittest_lite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lite_test-unittest_lite.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Tpo -c -o protobuf_lite_test-unittest_lite.pb.o `test -f 'google/protobuf/unittest_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Tpo $(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite.pb.cc' object='protobuf_lite_test-unittest_lite.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-strutil_unittest.o: google/protobuf/stubs/strutil_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-strutil_unittest.o -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-strutil_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-strutil_unittest.o `test -f 'google/protobuf/stubs/strutil_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/strutil_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-strutil_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-strutil_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/strutil_unittest.cc' object='google/protobuf/stubs/protobuf_test-strutil_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lite_test-unittest_lite.pb.o `test -f 'google/protobuf/unittest_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-strutil_unittest.o `test -f 'google/protobuf/stubs/strutil_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/strutil_unittest.cc -protobuf_lite_test-unittest_lite.pb.obj: google/protobuf/unittest_lite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lite_test-unittest_lite.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Tpo -c -o protobuf_lite_test-unittest_lite.pb.obj `if test -f 'google/protobuf/unittest_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Tpo $(DEPDIR)/protobuf_lite_test-unittest_lite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite.pb.cc' object='protobuf_lite_test-unittest_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-strutil_unittest.obj: google/protobuf/stubs/strutil_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-strutil_unittest.obj -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-strutil_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-strutil_unittest.obj `if test -f 'google/protobuf/stubs/strutil_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/strutil_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/strutil_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-strutil_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-strutil_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/strutil_unittest.cc' object='google/protobuf/stubs/protobuf_test-strutil_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lite_test-unittest_lite.pb.obj `if test -f 'google/protobuf/unittest_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-strutil_unittest.obj `if test -f 'google/protobuf/stubs/strutil_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/strutil_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/strutil_unittest.cc'; fi` -protobuf_lite_test-unittest_import_lite.pb.o: google/protobuf/unittest_import_lite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lite_test-unittest_import_lite.pb.o -MD -MP -MF $(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Tpo -c -o protobuf_lite_test-unittest_import_lite.pb.o `test -f 'google/protobuf/unittest_import_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_lite.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Tpo $(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_lite.pb.cc' object='protobuf_lite_test-unittest_import_lite.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-structurally_valid_unittest.o: google/protobuf/stubs/structurally_valid_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-structurally_valid_unittest.o -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-structurally_valid_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-structurally_valid_unittest.o `test -f 'google/protobuf/stubs/structurally_valid_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/structurally_valid_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-structurally_valid_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-structurally_valid_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/structurally_valid_unittest.cc' object='google/protobuf/stubs/protobuf_test-structurally_valid_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lite_test-unittest_import_lite.pb.o `test -f 'google/protobuf/unittest_import_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_lite.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-structurally_valid_unittest.o `test -f 'google/protobuf/stubs/structurally_valid_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/structurally_valid_unittest.cc -protobuf_lite_test-unittest_import_lite.pb.obj: google/protobuf/unittest_import_lite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_lite_test-unittest_import_lite.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Tpo -c -o protobuf_lite_test-unittest_import_lite.pb.obj `if test -f 'google/protobuf/unittest_import_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_lite.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Tpo $(DEPDIR)/protobuf_lite_test-unittest_import_lite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_lite.pb.cc' object='protobuf_lite_test-unittest_import_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-structurally_valid_unittest.obj: google/protobuf/stubs/structurally_valid_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-structurally_valid_unittest.obj -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-structurally_valid_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-structurally_valid_unittest.obj `if test -f 'google/protobuf/stubs/structurally_valid_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/structurally_valid_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/structurally_valid_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-structurally_valid_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-structurally_valid_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/structurally_valid_unittest.cc' object='google/protobuf/stubs/protobuf_test-structurally_valid_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protobuf_lite_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_lite_test-unittest_import_lite.pb.obj `if test -f 'google/protobuf/unittest_import_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_lite.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-structurally_valid_unittest.obj `if test -f 'google/protobuf/stubs/structurally_valid_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/structurally_valid_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/structurally_valid_unittest.cc'; fi` -protobuf_test-common_unittest.o: google/protobuf/stubs/common_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-common_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-common_unittest.Tpo -c -o protobuf_test-common_unittest.o `test -f 'google/protobuf/stubs/common_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/common_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-common_unittest.Tpo $(DEPDIR)/protobuf_test-common_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/common_unittest.cc' object='protobuf_test-common_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-stringprintf_unittest.o: google/protobuf/stubs/stringprintf_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-stringprintf_unittest.o -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-stringprintf_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-stringprintf_unittest.o `test -f 'google/protobuf/stubs/stringprintf_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/stringprintf_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-stringprintf_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-stringprintf_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/stringprintf_unittest.cc' object='google/protobuf/stubs/protobuf_test-stringprintf_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-common_unittest.o `test -f 'google/protobuf/stubs/common_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/common_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-stringprintf_unittest.o `test -f 'google/protobuf/stubs/stringprintf_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/stringprintf_unittest.cc -protobuf_test-common_unittest.obj: google/protobuf/stubs/common_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-common_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-common_unittest.Tpo -c -o protobuf_test-common_unittest.obj `if test -f 'google/protobuf/stubs/common_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/common_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/common_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-common_unittest.Tpo $(DEPDIR)/protobuf_test-common_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/common_unittest.cc' object='protobuf_test-common_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-stringprintf_unittest.obj: google/protobuf/stubs/stringprintf_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-stringprintf_unittest.obj -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-stringprintf_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-stringprintf_unittest.obj `if test -f 'google/protobuf/stubs/stringprintf_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/stringprintf_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/stringprintf_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-stringprintf_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-stringprintf_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/stringprintf_unittest.cc' object='google/protobuf/stubs/protobuf_test-stringprintf_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-common_unittest.obj `if test -f 'google/protobuf/stubs/common_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/common_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/common_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-stringprintf_unittest.obj `if test -f 'google/protobuf/stubs/stringprintf_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/stringprintf_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/stringprintf_unittest.cc'; fi` -protobuf_test-once_unittest.o: google/protobuf/stubs/once_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-once_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-once_unittest.Tpo -c -o protobuf_test-once_unittest.o `test -f 'google/protobuf/stubs/once_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/once_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-once_unittest.Tpo $(DEPDIR)/protobuf_test-once_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/once_unittest.cc' object='protobuf_test-once_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-template_util_unittest.o: google/protobuf/stubs/template_util_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-template_util_unittest.o -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-template_util_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-template_util_unittest.o `test -f 'google/protobuf/stubs/template_util_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/template_util_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-template_util_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-template_util_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/template_util_unittest.cc' object='google/protobuf/stubs/protobuf_test-template_util_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-once_unittest.o `test -f 'google/protobuf/stubs/once_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/once_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-template_util_unittest.o `test -f 'google/protobuf/stubs/template_util_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/template_util_unittest.cc -protobuf_test-once_unittest.obj: google/protobuf/stubs/once_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-once_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-once_unittest.Tpo -c -o protobuf_test-once_unittest.obj `if test -f 'google/protobuf/stubs/once_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/once_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/once_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-once_unittest.Tpo $(DEPDIR)/protobuf_test-once_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/once_unittest.cc' object='protobuf_test-once_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-template_util_unittest.obj: google/protobuf/stubs/template_util_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-template_util_unittest.obj -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-template_util_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-template_util_unittest.obj `if test -f 'google/protobuf/stubs/template_util_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/template_util_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/template_util_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-template_util_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-template_util_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/template_util_unittest.cc' object='google/protobuf/stubs/protobuf_test-template_util_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-once_unittest.obj `if test -f 'google/protobuf/stubs/once_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/once_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/once_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-template_util_unittest.obj `if test -f 'google/protobuf/stubs/template_util_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/template_util_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/template_util_unittest.cc'; fi` -protobuf_test-strutil_unittest.o: google/protobuf/stubs/strutil_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-strutil_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-strutil_unittest.Tpo -c -o protobuf_test-strutil_unittest.o `test -f 'google/protobuf/stubs/strutil_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/strutil_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-strutil_unittest.Tpo $(DEPDIR)/protobuf_test-strutil_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/strutil_unittest.cc' object='protobuf_test-strutil_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-type_traits_unittest.o: google/protobuf/stubs/type_traits_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-type_traits_unittest.o -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-type_traits_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-type_traits_unittest.o `test -f 'google/protobuf/stubs/type_traits_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/type_traits_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-type_traits_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-type_traits_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/type_traits_unittest.cc' object='google/protobuf/stubs/protobuf_test-type_traits_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-strutil_unittest.o `test -f 'google/protobuf/stubs/strutil_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/strutil_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-type_traits_unittest.o `test -f 'google/protobuf/stubs/type_traits_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/type_traits_unittest.cc -protobuf_test-strutil_unittest.obj: google/protobuf/stubs/strutil_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-strutil_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-strutil_unittest.Tpo -c -o protobuf_test-strutil_unittest.obj `if test -f 'google/protobuf/stubs/strutil_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/strutil_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/strutil_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-strutil_unittest.Tpo $(DEPDIR)/protobuf_test-strutil_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/strutil_unittest.cc' object='protobuf_test-strutil_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/stubs/protobuf_test-type_traits_unittest.obj: google/protobuf/stubs/type_traits_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/stubs/protobuf_test-type_traits_unittest.obj -MD -MP -MF google/protobuf/stubs/$(DEPDIR)/protobuf_test-type_traits_unittest.Tpo -c -o google/protobuf/stubs/protobuf_test-type_traits_unittest.obj `if test -f 'google/protobuf/stubs/type_traits_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/type_traits_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/type_traits_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/stubs/$(DEPDIR)/protobuf_test-type_traits_unittest.Tpo google/protobuf/stubs/$(DEPDIR)/protobuf_test-type_traits_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/type_traits_unittest.cc' object='google/protobuf/stubs/protobuf_test-type_traits_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-strutil_unittest.obj `if test -f 'google/protobuf/stubs/strutil_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/strutil_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/strutil_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/stubs/protobuf_test-type_traits_unittest.obj `if test -f 'google/protobuf/stubs/type_traits_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/type_traits_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/type_traits_unittest.cc'; fi` -protobuf_test-structurally_valid_unittest.o: google/protobuf/stubs/structurally_valid_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-structurally_valid_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-structurally_valid_unittest.Tpo -c -o protobuf_test-structurally_valid_unittest.o `test -f 'google/protobuf/stubs/structurally_valid_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/structurally_valid_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-structurally_valid_unittest.Tpo $(DEPDIR)/protobuf_test-structurally_valid_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/structurally_valid_unittest.cc' object='protobuf_test-structurally_valid_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-descriptor_database_unittest.o: google/protobuf/descriptor_database_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-descriptor_database_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-descriptor_database_unittest.Tpo -c -o google/protobuf/protobuf_test-descriptor_database_unittest.o `test -f 'google/protobuf/descriptor_database_unittest.cc' || echo '$(srcdir)/'`google/protobuf/descriptor_database_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-descriptor_database_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-descriptor_database_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/descriptor_database_unittest.cc' object='google/protobuf/protobuf_test-descriptor_database_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-structurally_valid_unittest.o `test -f 'google/protobuf/stubs/structurally_valid_unittest.cc' || echo '$(srcdir)/'`google/protobuf/stubs/structurally_valid_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-descriptor_database_unittest.o `test -f 'google/protobuf/descriptor_database_unittest.cc' || echo '$(srcdir)/'`google/protobuf/descriptor_database_unittest.cc -protobuf_test-structurally_valid_unittest.obj: google/protobuf/stubs/structurally_valid_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-structurally_valid_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-structurally_valid_unittest.Tpo -c -o protobuf_test-structurally_valid_unittest.obj `if test -f 'google/protobuf/stubs/structurally_valid_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/structurally_valid_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/structurally_valid_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-structurally_valid_unittest.Tpo $(DEPDIR)/protobuf_test-structurally_valid_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/stubs/structurally_valid_unittest.cc' object='protobuf_test-structurally_valid_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-descriptor_database_unittest.obj: google/protobuf/descriptor_database_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-descriptor_database_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-descriptor_database_unittest.Tpo -c -o google/protobuf/protobuf_test-descriptor_database_unittest.obj `if test -f 'google/protobuf/descriptor_database_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/descriptor_database_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/descriptor_database_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-descriptor_database_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-descriptor_database_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/descriptor_database_unittest.cc' object='google/protobuf/protobuf_test-descriptor_database_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-structurally_valid_unittest.obj `if test -f 'google/protobuf/stubs/structurally_valid_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/stubs/structurally_valid_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/stubs/structurally_valid_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-descriptor_database_unittest.obj `if test -f 'google/protobuf/descriptor_database_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/descriptor_database_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/descriptor_database_unittest.cc'; fi` -protobuf_test-descriptor_database_unittest.o: google/protobuf/descriptor_database_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-descriptor_database_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-descriptor_database_unittest.Tpo -c -o protobuf_test-descriptor_database_unittest.o `test -f 'google/protobuf/descriptor_database_unittest.cc' || echo '$(srcdir)/'`google/protobuf/descriptor_database_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-descriptor_database_unittest.Tpo $(DEPDIR)/protobuf_test-descriptor_database_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/descriptor_database_unittest.cc' object='protobuf_test-descriptor_database_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-descriptor_unittest.o: google/protobuf/descriptor_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-descriptor_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-descriptor_unittest.Tpo -c -o google/protobuf/protobuf_test-descriptor_unittest.o `test -f 'google/protobuf/descriptor_unittest.cc' || echo '$(srcdir)/'`google/protobuf/descriptor_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-descriptor_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-descriptor_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/descriptor_unittest.cc' object='google/protobuf/protobuf_test-descriptor_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-descriptor_database_unittest.o `test -f 'google/protobuf/descriptor_database_unittest.cc' || echo '$(srcdir)/'`google/protobuf/descriptor_database_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-descriptor_unittest.o `test -f 'google/protobuf/descriptor_unittest.cc' || echo '$(srcdir)/'`google/protobuf/descriptor_unittest.cc -protobuf_test-descriptor_database_unittest.obj: google/protobuf/descriptor_database_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-descriptor_database_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-descriptor_database_unittest.Tpo -c -o protobuf_test-descriptor_database_unittest.obj `if test -f 'google/protobuf/descriptor_database_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/descriptor_database_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/descriptor_database_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-descriptor_database_unittest.Tpo $(DEPDIR)/protobuf_test-descriptor_database_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/descriptor_database_unittest.cc' object='protobuf_test-descriptor_database_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-descriptor_unittest.obj: google/protobuf/descriptor_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-descriptor_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-descriptor_unittest.Tpo -c -o google/protobuf/protobuf_test-descriptor_unittest.obj `if test -f 'google/protobuf/descriptor_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/descriptor_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/descriptor_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-descriptor_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-descriptor_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/descriptor_unittest.cc' object='google/protobuf/protobuf_test-descriptor_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-descriptor_database_unittest.obj `if test -f 'google/protobuf/descriptor_database_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/descriptor_database_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/descriptor_database_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-descriptor_unittest.obj `if test -f 'google/protobuf/descriptor_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/descriptor_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/descriptor_unittest.cc'; fi` -protobuf_test-descriptor_unittest.o: google/protobuf/descriptor_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-descriptor_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-descriptor_unittest.Tpo -c -o protobuf_test-descriptor_unittest.o `test -f 'google/protobuf/descriptor_unittest.cc' || echo '$(srcdir)/'`google/protobuf/descriptor_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-descriptor_unittest.Tpo $(DEPDIR)/protobuf_test-descriptor_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/descriptor_unittest.cc' object='protobuf_test-descriptor_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-dynamic_message_unittest.o: google/protobuf/dynamic_message_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-dynamic_message_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-dynamic_message_unittest.Tpo -c -o google/protobuf/protobuf_test-dynamic_message_unittest.o `test -f 'google/protobuf/dynamic_message_unittest.cc' || echo '$(srcdir)/'`google/protobuf/dynamic_message_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-dynamic_message_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-dynamic_message_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/dynamic_message_unittest.cc' object='google/protobuf/protobuf_test-dynamic_message_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-descriptor_unittest.o `test -f 'google/protobuf/descriptor_unittest.cc' || echo '$(srcdir)/'`google/protobuf/descriptor_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-dynamic_message_unittest.o `test -f 'google/protobuf/dynamic_message_unittest.cc' || echo '$(srcdir)/'`google/protobuf/dynamic_message_unittest.cc -protobuf_test-descriptor_unittest.obj: google/protobuf/descriptor_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-descriptor_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-descriptor_unittest.Tpo -c -o protobuf_test-descriptor_unittest.obj `if test -f 'google/protobuf/descriptor_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/descriptor_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/descriptor_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-descriptor_unittest.Tpo $(DEPDIR)/protobuf_test-descriptor_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/descriptor_unittest.cc' object='protobuf_test-descriptor_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-dynamic_message_unittest.obj: google/protobuf/dynamic_message_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-dynamic_message_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-dynamic_message_unittest.Tpo -c -o google/protobuf/protobuf_test-dynamic_message_unittest.obj `if test -f 'google/protobuf/dynamic_message_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/dynamic_message_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/dynamic_message_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-dynamic_message_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-dynamic_message_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/dynamic_message_unittest.cc' object='google/protobuf/protobuf_test-dynamic_message_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-descriptor_unittest.obj `if test -f 'google/protobuf/descriptor_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/descriptor_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/descriptor_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-dynamic_message_unittest.obj `if test -f 'google/protobuf/dynamic_message_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/dynamic_message_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/dynamic_message_unittest.cc'; fi` -protobuf_test-dynamic_message_unittest.o: google/protobuf/dynamic_message_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-dynamic_message_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-dynamic_message_unittest.Tpo -c -o protobuf_test-dynamic_message_unittest.o `test -f 'google/protobuf/dynamic_message_unittest.cc' || echo '$(srcdir)/'`google/protobuf/dynamic_message_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-dynamic_message_unittest.Tpo $(DEPDIR)/protobuf_test-dynamic_message_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/dynamic_message_unittest.cc' object='protobuf_test-dynamic_message_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-extension_set_unittest.o: google/protobuf/extension_set_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-extension_set_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-extension_set_unittest.Tpo -c -o google/protobuf/protobuf_test-extension_set_unittest.o `test -f 'google/protobuf/extension_set_unittest.cc' || echo '$(srcdir)/'`google/protobuf/extension_set_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-extension_set_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-extension_set_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/extension_set_unittest.cc' object='google/protobuf/protobuf_test-extension_set_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-dynamic_message_unittest.o `test -f 'google/protobuf/dynamic_message_unittest.cc' || echo '$(srcdir)/'`google/protobuf/dynamic_message_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-extension_set_unittest.o `test -f 'google/protobuf/extension_set_unittest.cc' || echo '$(srcdir)/'`google/protobuf/extension_set_unittest.cc -protobuf_test-dynamic_message_unittest.obj: google/protobuf/dynamic_message_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-dynamic_message_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-dynamic_message_unittest.Tpo -c -o protobuf_test-dynamic_message_unittest.obj `if test -f 'google/protobuf/dynamic_message_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/dynamic_message_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/dynamic_message_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-dynamic_message_unittest.Tpo $(DEPDIR)/protobuf_test-dynamic_message_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/dynamic_message_unittest.cc' object='protobuf_test-dynamic_message_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-extension_set_unittest.obj: google/protobuf/extension_set_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-extension_set_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-extension_set_unittest.Tpo -c -o google/protobuf/protobuf_test-extension_set_unittest.obj `if test -f 'google/protobuf/extension_set_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/extension_set_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/extension_set_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-extension_set_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-extension_set_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/extension_set_unittest.cc' object='google/protobuf/protobuf_test-extension_set_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-dynamic_message_unittest.obj `if test -f 'google/protobuf/dynamic_message_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/dynamic_message_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/dynamic_message_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-extension_set_unittest.obj `if test -f 'google/protobuf/extension_set_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/extension_set_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/extension_set_unittest.cc'; fi` -protobuf_test-extension_set_unittest.o: google/protobuf/extension_set_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-extension_set_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-extension_set_unittest.Tpo -c -o protobuf_test-extension_set_unittest.o `test -f 'google/protobuf/extension_set_unittest.cc' || echo '$(srcdir)/'`google/protobuf/extension_set_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-extension_set_unittest.Tpo $(DEPDIR)/protobuf_test-extension_set_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/extension_set_unittest.cc' object='protobuf_test-extension_set_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-generated_message_reflection_unittest.o: google/protobuf/generated_message_reflection_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-generated_message_reflection_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Tpo -c -o google/protobuf/protobuf_test-generated_message_reflection_unittest.o `test -f 'google/protobuf/generated_message_reflection_unittest.cc' || echo '$(srcdir)/'`google/protobuf/generated_message_reflection_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/generated_message_reflection_unittest.cc' object='google/protobuf/protobuf_test-generated_message_reflection_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-extension_set_unittest.o `test -f 'google/protobuf/extension_set_unittest.cc' || echo '$(srcdir)/'`google/protobuf/extension_set_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-generated_message_reflection_unittest.o `test -f 'google/protobuf/generated_message_reflection_unittest.cc' || echo '$(srcdir)/'`google/protobuf/generated_message_reflection_unittest.cc -protobuf_test-extension_set_unittest.obj: google/protobuf/extension_set_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-extension_set_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-extension_set_unittest.Tpo -c -o protobuf_test-extension_set_unittest.obj `if test -f 'google/protobuf/extension_set_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/extension_set_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/extension_set_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-extension_set_unittest.Tpo $(DEPDIR)/protobuf_test-extension_set_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/extension_set_unittest.cc' object='protobuf_test-extension_set_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-generated_message_reflection_unittest.obj: google/protobuf/generated_message_reflection_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-generated_message_reflection_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Tpo -c -o google/protobuf/protobuf_test-generated_message_reflection_unittest.obj `if test -f 'google/protobuf/generated_message_reflection_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/generated_message_reflection_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/generated_message_reflection_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/generated_message_reflection_unittest.cc' object='google/protobuf/protobuf_test-generated_message_reflection_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-extension_set_unittest.obj `if test -f 'google/protobuf/extension_set_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/extension_set_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/extension_set_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-generated_message_reflection_unittest.obj `if test -f 'google/protobuf/generated_message_reflection_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/generated_message_reflection_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/generated_message_reflection_unittest.cc'; fi` -protobuf_test-generated_message_reflection_unittest.o: google/protobuf/generated_message_reflection_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-generated_message_reflection_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Tpo -c -o protobuf_test-generated_message_reflection_unittest.o `test -f 'google/protobuf/generated_message_reflection_unittest.cc' || echo '$(srcdir)/'`google/protobuf/generated_message_reflection_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Tpo $(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/generated_message_reflection_unittest.cc' object='protobuf_test-generated_message_reflection_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-message_unittest.o: google/protobuf/message_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-message_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-message_unittest.Tpo -c -o google/protobuf/protobuf_test-message_unittest.o `test -f 'google/protobuf/message_unittest.cc' || echo '$(srcdir)/'`google/protobuf/message_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-message_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-message_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/message_unittest.cc' object='google/protobuf/protobuf_test-message_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-generated_message_reflection_unittest.o `test -f 'google/protobuf/generated_message_reflection_unittest.cc' || echo '$(srcdir)/'`google/protobuf/generated_message_reflection_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-message_unittest.o `test -f 'google/protobuf/message_unittest.cc' || echo '$(srcdir)/'`google/protobuf/message_unittest.cc -protobuf_test-generated_message_reflection_unittest.obj: google/protobuf/generated_message_reflection_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-generated_message_reflection_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Tpo -c -o protobuf_test-generated_message_reflection_unittest.obj `if test -f 'google/protobuf/generated_message_reflection_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/generated_message_reflection_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/generated_message_reflection_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Tpo $(DEPDIR)/protobuf_test-generated_message_reflection_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/generated_message_reflection_unittest.cc' object='protobuf_test-generated_message_reflection_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-message_unittest.obj: google/protobuf/message_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-message_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-message_unittest.Tpo -c -o google/protobuf/protobuf_test-message_unittest.obj `if test -f 'google/protobuf/message_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/message_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/message_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-message_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-message_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/message_unittest.cc' object='google/protobuf/protobuf_test-message_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-generated_message_reflection_unittest.obj `if test -f 'google/protobuf/generated_message_reflection_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/generated_message_reflection_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/generated_message_reflection_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-message_unittest.obj `if test -f 'google/protobuf/message_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/message_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/message_unittest.cc'; fi` -protobuf_test-message_unittest.o: google/protobuf/message_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-message_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-message_unittest.Tpo -c -o protobuf_test-message_unittest.o `test -f 'google/protobuf/message_unittest.cc' || echo '$(srcdir)/'`google/protobuf/message_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-message_unittest.Tpo $(DEPDIR)/protobuf_test-message_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/message_unittest.cc' object='protobuf_test-message_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-reflection_ops_unittest.o: google/protobuf/reflection_ops_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-reflection_ops_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-reflection_ops_unittest.Tpo -c -o google/protobuf/protobuf_test-reflection_ops_unittest.o `test -f 'google/protobuf/reflection_ops_unittest.cc' || echo '$(srcdir)/'`google/protobuf/reflection_ops_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-reflection_ops_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-reflection_ops_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/reflection_ops_unittest.cc' object='google/protobuf/protobuf_test-reflection_ops_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-message_unittest.o `test -f 'google/protobuf/message_unittest.cc' || echo '$(srcdir)/'`google/protobuf/message_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-reflection_ops_unittest.o `test -f 'google/protobuf/reflection_ops_unittest.cc' || echo '$(srcdir)/'`google/protobuf/reflection_ops_unittest.cc -protobuf_test-message_unittest.obj: google/protobuf/message_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-message_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-message_unittest.Tpo -c -o protobuf_test-message_unittest.obj `if test -f 'google/protobuf/message_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/message_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/message_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-message_unittest.Tpo $(DEPDIR)/protobuf_test-message_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/message_unittest.cc' object='protobuf_test-message_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-reflection_ops_unittest.obj: google/protobuf/reflection_ops_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-reflection_ops_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-reflection_ops_unittest.Tpo -c -o google/protobuf/protobuf_test-reflection_ops_unittest.obj `if test -f 'google/protobuf/reflection_ops_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/reflection_ops_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/reflection_ops_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-reflection_ops_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-reflection_ops_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/reflection_ops_unittest.cc' object='google/protobuf/protobuf_test-reflection_ops_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-message_unittest.obj `if test -f 'google/protobuf/message_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/message_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/message_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-reflection_ops_unittest.obj `if test -f 'google/protobuf/reflection_ops_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/reflection_ops_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/reflection_ops_unittest.cc'; fi` -protobuf_test-reflection_ops_unittest.o: google/protobuf/reflection_ops_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-reflection_ops_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-reflection_ops_unittest.Tpo -c -o protobuf_test-reflection_ops_unittest.o `test -f 'google/protobuf/reflection_ops_unittest.cc' || echo '$(srcdir)/'`google/protobuf/reflection_ops_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-reflection_ops_unittest.Tpo $(DEPDIR)/protobuf_test-reflection_ops_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/reflection_ops_unittest.cc' object='protobuf_test-reflection_ops_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-repeated_field_unittest.o: google/protobuf/repeated_field_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-repeated_field_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_unittest.Tpo -c -o google/protobuf/protobuf_test-repeated_field_unittest.o `test -f 'google/protobuf/repeated_field_unittest.cc' || echo '$(srcdir)/'`google/protobuf/repeated_field_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/repeated_field_unittest.cc' object='google/protobuf/protobuf_test-repeated_field_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-reflection_ops_unittest.o `test -f 'google/protobuf/reflection_ops_unittest.cc' || echo '$(srcdir)/'`google/protobuf/reflection_ops_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-repeated_field_unittest.o `test -f 'google/protobuf/repeated_field_unittest.cc' || echo '$(srcdir)/'`google/protobuf/repeated_field_unittest.cc -protobuf_test-reflection_ops_unittest.obj: google/protobuf/reflection_ops_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-reflection_ops_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-reflection_ops_unittest.Tpo -c -o protobuf_test-reflection_ops_unittest.obj `if test -f 'google/protobuf/reflection_ops_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/reflection_ops_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/reflection_ops_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-reflection_ops_unittest.Tpo $(DEPDIR)/protobuf_test-reflection_ops_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/reflection_ops_unittest.cc' object='protobuf_test-reflection_ops_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-repeated_field_unittest.obj: google/protobuf/repeated_field_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-repeated_field_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_unittest.Tpo -c -o google/protobuf/protobuf_test-repeated_field_unittest.obj `if test -f 'google/protobuf/repeated_field_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/repeated_field_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/repeated_field_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/repeated_field_unittest.cc' object='google/protobuf/protobuf_test-repeated_field_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-reflection_ops_unittest.obj `if test -f 'google/protobuf/reflection_ops_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/reflection_ops_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/reflection_ops_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-repeated_field_unittest.obj `if test -f 'google/protobuf/repeated_field_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/repeated_field_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/repeated_field_unittest.cc'; fi` -protobuf_test-repeated_field_unittest.o: google/protobuf/repeated_field_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-repeated_field_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-repeated_field_unittest.Tpo -c -o protobuf_test-repeated_field_unittest.o `test -f 'google/protobuf/repeated_field_unittest.cc' || echo '$(srcdir)/'`google/protobuf/repeated_field_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-repeated_field_unittest.Tpo $(DEPDIR)/protobuf_test-repeated_field_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/repeated_field_unittest.cc' object='protobuf_test-repeated_field_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-repeated_field_reflection_unittest.o: google/protobuf/repeated_field_reflection_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-repeated_field_reflection_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_reflection_unittest.Tpo -c -o google/protobuf/protobuf_test-repeated_field_reflection_unittest.o `test -f 'google/protobuf/repeated_field_reflection_unittest.cc' || echo '$(srcdir)/'`google/protobuf/repeated_field_reflection_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_reflection_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_reflection_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/repeated_field_reflection_unittest.cc' object='google/protobuf/protobuf_test-repeated_field_reflection_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-repeated_field_unittest.o `test -f 'google/protobuf/repeated_field_unittest.cc' || echo '$(srcdir)/'`google/protobuf/repeated_field_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-repeated_field_reflection_unittest.o `test -f 'google/protobuf/repeated_field_reflection_unittest.cc' || echo '$(srcdir)/'`google/protobuf/repeated_field_reflection_unittest.cc -protobuf_test-repeated_field_unittest.obj: google/protobuf/repeated_field_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-repeated_field_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-repeated_field_unittest.Tpo -c -o protobuf_test-repeated_field_unittest.obj `if test -f 'google/protobuf/repeated_field_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/repeated_field_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/repeated_field_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-repeated_field_unittest.Tpo $(DEPDIR)/protobuf_test-repeated_field_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/repeated_field_unittest.cc' object='protobuf_test-repeated_field_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-repeated_field_reflection_unittest.obj: google/protobuf/repeated_field_reflection_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-repeated_field_reflection_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_reflection_unittest.Tpo -c -o google/protobuf/protobuf_test-repeated_field_reflection_unittest.obj `if test -f 'google/protobuf/repeated_field_reflection_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/repeated_field_reflection_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/repeated_field_reflection_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_reflection_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-repeated_field_reflection_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/repeated_field_reflection_unittest.cc' object='google/protobuf/protobuf_test-repeated_field_reflection_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-repeated_field_unittest.obj `if test -f 'google/protobuf/repeated_field_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/repeated_field_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/repeated_field_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-repeated_field_reflection_unittest.obj `if test -f 'google/protobuf/repeated_field_reflection_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/repeated_field_reflection_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/repeated_field_reflection_unittest.cc'; fi` -protobuf_test-text_format_unittest.o: google/protobuf/text_format_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-text_format_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-text_format_unittest.Tpo -c -o protobuf_test-text_format_unittest.o `test -f 'google/protobuf/text_format_unittest.cc' || echo '$(srcdir)/'`google/protobuf/text_format_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-text_format_unittest.Tpo $(DEPDIR)/protobuf_test-text_format_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/text_format_unittest.cc' object='protobuf_test-text_format_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-text_format_unittest.o: google/protobuf/text_format_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-text_format_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-text_format_unittest.Tpo -c -o google/protobuf/protobuf_test-text_format_unittest.o `test -f 'google/protobuf/text_format_unittest.cc' || echo '$(srcdir)/'`google/protobuf/text_format_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-text_format_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-text_format_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/text_format_unittest.cc' object='google/protobuf/protobuf_test-text_format_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-text_format_unittest.o `test -f 'google/protobuf/text_format_unittest.cc' || echo '$(srcdir)/'`google/protobuf/text_format_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-text_format_unittest.o `test -f 'google/protobuf/text_format_unittest.cc' || echo '$(srcdir)/'`google/protobuf/text_format_unittest.cc -protobuf_test-text_format_unittest.obj: google/protobuf/text_format_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-text_format_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-text_format_unittest.Tpo -c -o protobuf_test-text_format_unittest.obj `if test -f 'google/protobuf/text_format_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/text_format_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/text_format_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-text_format_unittest.Tpo $(DEPDIR)/protobuf_test-text_format_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/text_format_unittest.cc' object='protobuf_test-text_format_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-text_format_unittest.obj: google/protobuf/text_format_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-text_format_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-text_format_unittest.Tpo -c -o google/protobuf/protobuf_test-text_format_unittest.obj `if test -f 'google/protobuf/text_format_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/text_format_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/text_format_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-text_format_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-text_format_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/text_format_unittest.cc' object='google/protobuf/protobuf_test-text_format_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-text_format_unittest.obj `if test -f 'google/protobuf/text_format_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/text_format_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/text_format_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-text_format_unittest.obj `if test -f 'google/protobuf/text_format_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/text_format_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/text_format_unittest.cc'; fi` -protobuf_test-unknown_field_set_unittest.o: google/protobuf/unknown_field_set_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unknown_field_set_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-unknown_field_set_unittest.Tpo -c -o protobuf_test-unknown_field_set_unittest.o `test -f 'google/protobuf/unknown_field_set_unittest.cc' || echo '$(srcdir)/'`google/protobuf/unknown_field_set_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unknown_field_set_unittest.Tpo $(DEPDIR)/protobuf_test-unknown_field_set_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unknown_field_set_unittest.cc' object='protobuf_test-unknown_field_set_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unknown_field_set_unittest.o: google/protobuf/unknown_field_set_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unknown_field_set_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unknown_field_set_unittest.Tpo -c -o google/protobuf/protobuf_test-unknown_field_set_unittest.o `test -f 'google/protobuf/unknown_field_set_unittest.cc' || echo '$(srcdir)/'`google/protobuf/unknown_field_set_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unknown_field_set_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unknown_field_set_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unknown_field_set_unittest.cc' object='google/protobuf/protobuf_test-unknown_field_set_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unknown_field_set_unittest.o `test -f 'google/protobuf/unknown_field_set_unittest.cc' || echo '$(srcdir)/'`google/protobuf/unknown_field_set_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unknown_field_set_unittest.o `test -f 'google/protobuf/unknown_field_set_unittest.cc' || echo '$(srcdir)/'`google/protobuf/unknown_field_set_unittest.cc -protobuf_test-unknown_field_set_unittest.obj: google/protobuf/unknown_field_set_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unknown_field_set_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-unknown_field_set_unittest.Tpo -c -o protobuf_test-unknown_field_set_unittest.obj `if test -f 'google/protobuf/unknown_field_set_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/unknown_field_set_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unknown_field_set_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unknown_field_set_unittest.Tpo $(DEPDIR)/protobuf_test-unknown_field_set_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unknown_field_set_unittest.cc' object='protobuf_test-unknown_field_set_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unknown_field_set_unittest.obj: google/protobuf/unknown_field_set_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unknown_field_set_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unknown_field_set_unittest.Tpo -c -o google/protobuf/protobuf_test-unknown_field_set_unittest.obj `if test -f 'google/protobuf/unknown_field_set_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/unknown_field_set_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unknown_field_set_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unknown_field_set_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unknown_field_set_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unknown_field_set_unittest.cc' object='google/protobuf/protobuf_test-unknown_field_set_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unknown_field_set_unittest.obj `if test -f 'google/protobuf/unknown_field_set_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/unknown_field_set_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unknown_field_set_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unknown_field_set_unittest.obj `if test -f 'google/protobuf/unknown_field_set_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/unknown_field_set_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unknown_field_set_unittest.cc'; fi` -protobuf_test-wire_format_unittest.o: google/protobuf/wire_format_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-wire_format_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-wire_format_unittest.Tpo -c -o protobuf_test-wire_format_unittest.o `test -f 'google/protobuf/wire_format_unittest.cc' || echo '$(srcdir)/'`google/protobuf/wire_format_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-wire_format_unittest.Tpo $(DEPDIR)/protobuf_test-wire_format_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/wire_format_unittest.cc' object='protobuf_test-wire_format_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-wire_format_unittest.o: google/protobuf/wire_format_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-wire_format_unittest.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-wire_format_unittest.Tpo -c -o google/protobuf/protobuf_test-wire_format_unittest.o `test -f 'google/protobuf/wire_format_unittest.cc' || echo '$(srcdir)/'`google/protobuf/wire_format_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-wire_format_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-wire_format_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/wire_format_unittest.cc' object='google/protobuf/protobuf_test-wire_format_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-wire_format_unittest.o `test -f 'google/protobuf/wire_format_unittest.cc' || echo '$(srcdir)/'`google/protobuf/wire_format_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-wire_format_unittest.o `test -f 'google/protobuf/wire_format_unittest.cc' || echo '$(srcdir)/'`google/protobuf/wire_format_unittest.cc -protobuf_test-wire_format_unittest.obj: google/protobuf/wire_format_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-wire_format_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-wire_format_unittest.Tpo -c -o protobuf_test-wire_format_unittest.obj `if test -f 'google/protobuf/wire_format_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/wire_format_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/wire_format_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-wire_format_unittest.Tpo $(DEPDIR)/protobuf_test-wire_format_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/wire_format_unittest.cc' object='protobuf_test-wire_format_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-wire_format_unittest.obj: google/protobuf/wire_format_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-wire_format_unittest.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-wire_format_unittest.Tpo -c -o google/protobuf/protobuf_test-wire_format_unittest.obj `if test -f 'google/protobuf/wire_format_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/wire_format_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/wire_format_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-wire_format_unittest.Tpo google/protobuf/$(DEPDIR)/protobuf_test-wire_format_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/wire_format_unittest.cc' object='google/protobuf/protobuf_test-wire_format_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-wire_format_unittest.obj `if test -f 'google/protobuf/wire_format_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/wire_format_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/wire_format_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-wire_format_unittest.obj `if test -f 'google/protobuf/wire_format_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/wire_format_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/wire_format_unittest.cc'; fi` -protobuf_test-coded_stream_unittest.o: google/protobuf/io/coded_stream_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-coded_stream_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-coded_stream_unittest.Tpo -c -o protobuf_test-coded_stream_unittest.o `test -f 'google/protobuf/io/coded_stream_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/coded_stream_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-coded_stream_unittest.Tpo $(DEPDIR)/protobuf_test-coded_stream_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/coded_stream_unittest.cc' object='protobuf_test-coded_stream_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/io/protobuf_test-coded_stream_unittest.o: google/protobuf/io/coded_stream_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/io/protobuf_test-coded_stream_unittest.o -MD -MP -MF google/protobuf/io/$(DEPDIR)/protobuf_test-coded_stream_unittest.Tpo -c -o google/protobuf/io/protobuf_test-coded_stream_unittest.o `test -f 'google/protobuf/io/coded_stream_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/coded_stream_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/io/$(DEPDIR)/protobuf_test-coded_stream_unittest.Tpo google/protobuf/io/$(DEPDIR)/protobuf_test-coded_stream_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/coded_stream_unittest.cc' object='google/protobuf/io/protobuf_test-coded_stream_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-coded_stream_unittest.o `test -f 'google/protobuf/io/coded_stream_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/coded_stream_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/io/protobuf_test-coded_stream_unittest.o `test -f 'google/protobuf/io/coded_stream_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/coded_stream_unittest.cc -protobuf_test-coded_stream_unittest.obj: google/protobuf/io/coded_stream_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-coded_stream_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-coded_stream_unittest.Tpo -c -o protobuf_test-coded_stream_unittest.obj `if test -f 'google/protobuf/io/coded_stream_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/coded_stream_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/coded_stream_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-coded_stream_unittest.Tpo $(DEPDIR)/protobuf_test-coded_stream_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/coded_stream_unittest.cc' object='protobuf_test-coded_stream_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/io/protobuf_test-coded_stream_unittest.obj: google/protobuf/io/coded_stream_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/io/protobuf_test-coded_stream_unittest.obj -MD -MP -MF google/protobuf/io/$(DEPDIR)/protobuf_test-coded_stream_unittest.Tpo -c -o google/protobuf/io/protobuf_test-coded_stream_unittest.obj `if test -f 'google/protobuf/io/coded_stream_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/coded_stream_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/coded_stream_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/io/$(DEPDIR)/protobuf_test-coded_stream_unittest.Tpo google/protobuf/io/$(DEPDIR)/protobuf_test-coded_stream_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/coded_stream_unittest.cc' object='google/protobuf/io/protobuf_test-coded_stream_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-coded_stream_unittest.obj `if test -f 'google/protobuf/io/coded_stream_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/coded_stream_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/coded_stream_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/io/protobuf_test-coded_stream_unittest.obj `if test -f 'google/protobuf/io/coded_stream_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/coded_stream_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/coded_stream_unittest.cc'; fi` -protobuf_test-printer_unittest.o: google/protobuf/io/printer_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-printer_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-printer_unittest.Tpo -c -o protobuf_test-printer_unittest.o `test -f 'google/protobuf/io/printer_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/printer_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-printer_unittest.Tpo $(DEPDIR)/protobuf_test-printer_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/printer_unittest.cc' object='protobuf_test-printer_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/io/protobuf_test-printer_unittest.o: google/protobuf/io/printer_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/io/protobuf_test-printer_unittest.o -MD -MP -MF google/protobuf/io/$(DEPDIR)/protobuf_test-printer_unittest.Tpo -c -o google/protobuf/io/protobuf_test-printer_unittest.o `test -f 'google/protobuf/io/printer_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/printer_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/io/$(DEPDIR)/protobuf_test-printer_unittest.Tpo google/protobuf/io/$(DEPDIR)/protobuf_test-printer_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/printer_unittest.cc' object='google/protobuf/io/protobuf_test-printer_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-printer_unittest.o `test -f 'google/protobuf/io/printer_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/printer_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/io/protobuf_test-printer_unittest.o `test -f 'google/protobuf/io/printer_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/printer_unittest.cc -protobuf_test-printer_unittest.obj: google/protobuf/io/printer_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-printer_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-printer_unittest.Tpo -c -o protobuf_test-printer_unittest.obj `if test -f 'google/protobuf/io/printer_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/printer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/printer_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-printer_unittest.Tpo $(DEPDIR)/protobuf_test-printer_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/printer_unittest.cc' object='protobuf_test-printer_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/io/protobuf_test-printer_unittest.obj: google/protobuf/io/printer_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/io/protobuf_test-printer_unittest.obj -MD -MP -MF google/protobuf/io/$(DEPDIR)/protobuf_test-printer_unittest.Tpo -c -o google/protobuf/io/protobuf_test-printer_unittest.obj `if test -f 'google/protobuf/io/printer_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/printer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/printer_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/io/$(DEPDIR)/protobuf_test-printer_unittest.Tpo google/protobuf/io/$(DEPDIR)/protobuf_test-printer_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/printer_unittest.cc' object='google/protobuf/io/protobuf_test-printer_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-printer_unittest.obj `if test -f 'google/protobuf/io/printer_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/printer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/printer_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/io/protobuf_test-printer_unittest.obj `if test -f 'google/protobuf/io/printer_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/printer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/printer_unittest.cc'; fi` -protobuf_test-tokenizer_unittest.o: google/protobuf/io/tokenizer_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-tokenizer_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-tokenizer_unittest.Tpo -c -o protobuf_test-tokenizer_unittest.o `test -f 'google/protobuf/io/tokenizer_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/tokenizer_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-tokenizer_unittest.Tpo $(DEPDIR)/protobuf_test-tokenizer_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/tokenizer_unittest.cc' object='protobuf_test-tokenizer_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/io/protobuf_test-tokenizer_unittest.o: google/protobuf/io/tokenizer_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/io/protobuf_test-tokenizer_unittest.o -MD -MP -MF google/protobuf/io/$(DEPDIR)/protobuf_test-tokenizer_unittest.Tpo -c -o google/protobuf/io/protobuf_test-tokenizer_unittest.o `test -f 'google/protobuf/io/tokenizer_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/tokenizer_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/io/$(DEPDIR)/protobuf_test-tokenizer_unittest.Tpo google/protobuf/io/$(DEPDIR)/protobuf_test-tokenizer_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/tokenizer_unittest.cc' object='google/protobuf/io/protobuf_test-tokenizer_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-tokenizer_unittest.o `test -f 'google/protobuf/io/tokenizer_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/tokenizer_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/io/protobuf_test-tokenizer_unittest.o `test -f 'google/protobuf/io/tokenizer_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/tokenizer_unittest.cc -protobuf_test-tokenizer_unittest.obj: google/protobuf/io/tokenizer_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-tokenizer_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-tokenizer_unittest.Tpo -c -o protobuf_test-tokenizer_unittest.obj `if test -f 'google/protobuf/io/tokenizer_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/tokenizer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/tokenizer_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-tokenizer_unittest.Tpo $(DEPDIR)/protobuf_test-tokenizer_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/tokenizer_unittest.cc' object='protobuf_test-tokenizer_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/io/protobuf_test-tokenizer_unittest.obj: google/protobuf/io/tokenizer_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/io/protobuf_test-tokenizer_unittest.obj -MD -MP -MF google/protobuf/io/$(DEPDIR)/protobuf_test-tokenizer_unittest.Tpo -c -o google/protobuf/io/protobuf_test-tokenizer_unittest.obj `if test -f 'google/protobuf/io/tokenizer_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/tokenizer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/tokenizer_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/io/$(DEPDIR)/protobuf_test-tokenizer_unittest.Tpo google/protobuf/io/$(DEPDIR)/protobuf_test-tokenizer_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/tokenizer_unittest.cc' object='google/protobuf/io/protobuf_test-tokenizer_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-tokenizer_unittest.obj `if test -f 'google/protobuf/io/tokenizer_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/tokenizer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/tokenizer_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/io/protobuf_test-tokenizer_unittest.obj `if test -f 'google/protobuf/io/tokenizer_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/tokenizer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/tokenizer_unittest.cc'; fi` -protobuf_test-zero_copy_stream_unittest.o: google/protobuf/io/zero_copy_stream_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-zero_copy_stream_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Tpo -c -o protobuf_test-zero_copy_stream_unittest.o `test -f 'google/protobuf/io/zero_copy_stream_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/zero_copy_stream_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Tpo $(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/zero_copy_stream_unittest.cc' object='protobuf_test-zero_copy_stream_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/io/protobuf_test-zero_copy_stream_unittest.o: google/protobuf/io/zero_copy_stream_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/io/protobuf_test-zero_copy_stream_unittest.o -MD -MP -MF google/protobuf/io/$(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Tpo -c -o google/protobuf/io/protobuf_test-zero_copy_stream_unittest.o `test -f 'google/protobuf/io/zero_copy_stream_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/zero_copy_stream_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/io/$(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Tpo google/protobuf/io/$(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/zero_copy_stream_unittest.cc' object='google/protobuf/io/protobuf_test-zero_copy_stream_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-zero_copy_stream_unittest.o `test -f 'google/protobuf/io/zero_copy_stream_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/zero_copy_stream_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/io/protobuf_test-zero_copy_stream_unittest.o `test -f 'google/protobuf/io/zero_copy_stream_unittest.cc' || echo '$(srcdir)/'`google/protobuf/io/zero_copy_stream_unittest.cc -protobuf_test-zero_copy_stream_unittest.obj: google/protobuf/io/zero_copy_stream_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-zero_copy_stream_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Tpo -c -o protobuf_test-zero_copy_stream_unittest.obj `if test -f 'google/protobuf/io/zero_copy_stream_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/zero_copy_stream_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/zero_copy_stream_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Tpo $(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/zero_copy_stream_unittest.cc' object='protobuf_test-zero_copy_stream_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/io/protobuf_test-zero_copy_stream_unittest.obj: google/protobuf/io/zero_copy_stream_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/io/protobuf_test-zero_copy_stream_unittest.obj -MD -MP -MF google/protobuf/io/$(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Tpo -c -o google/protobuf/io/protobuf_test-zero_copy_stream_unittest.obj `if test -f 'google/protobuf/io/zero_copy_stream_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/zero_copy_stream_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/zero_copy_stream_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/io/$(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Tpo google/protobuf/io/$(DEPDIR)/protobuf_test-zero_copy_stream_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/io/zero_copy_stream_unittest.cc' object='google/protobuf/io/protobuf_test-zero_copy_stream_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-zero_copy_stream_unittest.obj `if test -f 'google/protobuf/io/zero_copy_stream_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/zero_copy_stream_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/zero_copy_stream_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/io/protobuf_test-zero_copy_stream_unittest.obj `if test -f 'google/protobuf/io/zero_copy_stream_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/io/zero_copy_stream_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/io/zero_copy_stream_unittest.cc'; fi` -protobuf_test-command_line_interface_unittest.o: google/protobuf/compiler/command_line_interface_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-command_line_interface_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-command_line_interface_unittest.Tpo -c -o protobuf_test-command_line_interface_unittest.o `test -f 'google/protobuf/compiler/command_line_interface_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/command_line_interface_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-command_line_interface_unittest.Tpo $(DEPDIR)/protobuf_test-command_line_interface_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/command_line_interface_unittest.cc' object='protobuf_test-command_line_interface_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/protobuf_test-command_line_interface_unittest.o: google/protobuf/compiler/command_line_interface_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/protobuf_test-command_line_interface_unittest.o -MD -MP -MF google/protobuf/compiler/$(DEPDIR)/protobuf_test-command_line_interface_unittest.Tpo -c -o google/protobuf/compiler/protobuf_test-command_line_interface_unittest.o `test -f 'google/protobuf/compiler/command_line_interface_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/command_line_interface_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/$(DEPDIR)/protobuf_test-command_line_interface_unittest.Tpo google/protobuf/compiler/$(DEPDIR)/protobuf_test-command_line_interface_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/command_line_interface_unittest.cc' object='google/protobuf/compiler/protobuf_test-command_line_interface_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-command_line_interface_unittest.o `test -f 'google/protobuf/compiler/command_line_interface_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/command_line_interface_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/protobuf_test-command_line_interface_unittest.o `test -f 'google/protobuf/compiler/command_line_interface_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/command_line_interface_unittest.cc -protobuf_test-command_line_interface_unittest.obj: google/protobuf/compiler/command_line_interface_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-command_line_interface_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-command_line_interface_unittest.Tpo -c -o protobuf_test-command_line_interface_unittest.obj `if test -f 'google/protobuf/compiler/command_line_interface_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/command_line_interface_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/command_line_interface_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-command_line_interface_unittest.Tpo $(DEPDIR)/protobuf_test-command_line_interface_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/command_line_interface_unittest.cc' object='protobuf_test-command_line_interface_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/protobuf_test-command_line_interface_unittest.obj: google/protobuf/compiler/command_line_interface_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/protobuf_test-command_line_interface_unittest.obj -MD -MP -MF google/protobuf/compiler/$(DEPDIR)/protobuf_test-command_line_interface_unittest.Tpo -c -o google/protobuf/compiler/protobuf_test-command_line_interface_unittest.obj `if test -f 'google/protobuf/compiler/command_line_interface_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/command_line_interface_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/command_line_interface_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/$(DEPDIR)/protobuf_test-command_line_interface_unittest.Tpo google/protobuf/compiler/$(DEPDIR)/protobuf_test-command_line_interface_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/command_line_interface_unittest.cc' object='google/protobuf/compiler/protobuf_test-command_line_interface_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-command_line_interface_unittest.obj `if test -f 'google/protobuf/compiler/command_line_interface_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/command_line_interface_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/command_line_interface_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/protobuf_test-command_line_interface_unittest.obj `if test -f 'google/protobuf/compiler/command_line_interface_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/command_line_interface_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/command_line_interface_unittest.cc'; fi` -protobuf_test-importer_unittest.o: google/protobuf/compiler/importer_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-importer_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-importer_unittest.Tpo -c -o protobuf_test-importer_unittest.o `test -f 'google/protobuf/compiler/importer_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/importer_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-importer_unittest.Tpo $(DEPDIR)/protobuf_test-importer_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/importer_unittest.cc' object='protobuf_test-importer_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/protobuf_test-importer_unittest.o: google/protobuf/compiler/importer_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/protobuf_test-importer_unittest.o -MD -MP -MF google/protobuf/compiler/$(DEPDIR)/protobuf_test-importer_unittest.Tpo -c -o google/protobuf/compiler/protobuf_test-importer_unittest.o `test -f 'google/protobuf/compiler/importer_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/importer_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/$(DEPDIR)/protobuf_test-importer_unittest.Tpo google/protobuf/compiler/$(DEPDIR)/protobuf_test-importer_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/importer_unittest.cc' object='google/protobuf/compiler/protobuf_test-importer_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-importer_unittest.o `test -f 'google/protobuf/compiler/importer_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/importer_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/protobuf_test-importer_unittest.o `test -f 'google/protobuf/compiler/importer_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/importer_unittest.cc -protobuf_test-importer_unittest.obj: google/protobuf/compiler/importer_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-importer_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-importer_unittest.Tpo -c -o protobuf_test-importer_unittest.obj `if test -f 'google/protobuf/compiler/importer_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/importer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/importer_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-importer_unittest.Tpo $(DEPDIR)/protobuf_test-importer_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/importer_unittest.cc' object='protobuf_test-importer_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/protobuf_test-importer_unittest.obj: google/protobuf/compiler/importer_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/protobuf_test-importer_unittest.obj -MD -MP -MF google/protobuf/compiler/$(DEPDIR)/protobuf_test-importer_unittest.Tpo -c -o google/protobuf/compiler/protobuf_test-importer_unittest.obj `if test -f 'google/protobuf/compiler/importer_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/importer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/importer_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/$(DEPDIR)/protobuf_test-importer_unittest.Tpo google/protobuf/compiler/$(DEPDIR)/protobuf_test-importer_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/importer_unittest.cc' object='google/protobuf/compiler/protobuf_test-importer_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-importer_unittest.obj `if test -f 'google/protobuf/compiler/importer_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/importer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/importer_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/protobuf_test-importer_unittest.obj `if test -f 'google/protobuf/compiler/importer_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/importer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/importer_unittest.cc'; fi` -protobuf_test-mock_code_generator.o: google/protobuf/compiler/mock_code_generator.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-mock_code_generator.o -MD -MP -MF $(DEPDIR)/protobuf_test-mock_code_generator.Tpo -c -o protobuf_test-mock_code_generator.o `test -f 'google/protobuf/compiler/mock_code_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/mock_code_generator.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-mock_code_generator.Tpo $(DEPDIR)/protobuf_test-mock_code_generator.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/mock_code_generator.cc' object='protobuf_test-mock_code_generator.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/protobuf_test-mock_code_generator.o: google/protobuf/compiler/mock_code_generator.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/protobuf_test-mock_code_generator.o -MD -MP -MF google/protobuf/compiler/$(DEPDIR)/protobuf_test-mock_code_generator.Tpo -c -o google/protobuf/compiler/protobuf_test-mock_code_generator.o `test -f 'google/protobuf/compiler/mock_code_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/mock_code_generator.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/$(DEPDIR)/protobuf_test-mock_code_generator.Tpo google/protobuf/compiler/$(DEPDIR)/protobuf_test-mock_code_generator.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/mock_code_generator.cc' object='google/protobuf/compiler/protobuf_test-mock_code_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-mock_code_generator.o `test -f 'google/protobuf/compiler/mock_code_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/mock_code_generator.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/protobuf_test-mock_code_generator.o `test -f 'google/protobuf/compiler/mock_code_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/mock_code_generator.cc -protobuf_test-mock_code_generator.obj: google/protobuf/compiler/mock_code_generator.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-mock_code_generator.obj -MD -MP -MF $(DEPDIR)/protobuf_test-mock_code_generator.Tpo -c -o protobuf_test-mock_code_generator.obj `if test -f 'google/protobuf/compiler/mock_code_generator.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/mock_code_generator.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/mock_code_generator.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-mock_code_generator.Tpo $(DEPDIR)/protobuf_test-mock_code_generator.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/mock_code_generator.cc' object='protobuf_test-mock_code_generator.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/protobuf_test-mock_code_generator.obj: google/protobuf/compiler/mock_code_generator.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/protobuf_test-mock_code_generator.obj -MD -MP -MF google/protobuf/compiler/$(DEPDIR)/protobuf_test-mock_code_generator.Tpo -c -o google/protobuf/compiler/protobuf_test-mock_code_generator.obj `if test -f 'google/protobuf/compiler/mock_code_generator.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/mock_code_generator.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/mock_code_generator.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/$(DEPDIR)/protobuf_test-mock_code_generator.Tpo google/protobuf/compiler/$(DEPDIR)/protobuf_test-mock_code_generator.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/mock_code_generator.cc' object='google/protobuf/compiler/protobuf_test-mock_code_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-mock_code_generator.obj `if test -f 'google/protobuf/compiler/mock_code_generator.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/mock_code_generator.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/mock_code_generator.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/protobuf_test-mock_code_generator.obj `if test -f 'google/protobuf/compiler/mock_code_generator.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/mock_code_generator.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/mock_code_generator.cc'; fi` -protobuf_test-parser_unittest.o: google/protobuf/compiler/parser_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-parser_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-parser_unittest.Tpo -c -o protobuf_test-parser_unittest.o `test -f 'google/protobuf/compiler/parser_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/parser_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-parser_unittest.Tpo $(DEPDIR)/protobuf_test-parser_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/parser_unittest.cc' object='protobuf_test-parser_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/protobuf_test-parser_unittest.o: google/protobuf/compiler/parser_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/protobuf_test-parser_unittest.o -MD -MP -MF google/protobuf/compiler/$(DEPDIR)/protobuf_test-parser_unittest.Tpo -c -o google/protobuf/compiler/protobuf_test-parser_unittest.o `test -f 'google/protobuf/compiler/parser_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/parser_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/$(DEPDIR)/protobuf_test-parser_unittest.Tpo google/protobuf/compiler/$(DEPDIR)/protobuf_test-parser_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/parser_unittest.cc' object='google/protobuf/compiler/protobuf_test-parser_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-parser_unittest.o `test -f 'google/protobuf/compiler/parser_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/parser_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/protobuf_test-parser_unittest.o `test -f 'google/protobuf/compiler/parser_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/parser_unittest.cc -protobuf_test-parser_unittest.obj: google/protobuf/compiler/parser_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-parser_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-parser_unittest.Tpo -c -o protobuf_test-parser_unittest.obj `if test -f 'google/protobuf/compiler/parser_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/parser_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/parser_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-parser_unittest.Tpo $(DEPDIR)/protobuf_test-parser_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/parser_unittest.cc' object='protobuf_test-parser_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/protobuf_test-parser_unittest.obj: google/protobuf/compiler/parser_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/protobuf_test-parser_unittest.obj -MD -MP -MF google/protobuf/compiler/$(DEPDIR)/protobuf_test-parser_unittest.Tpo -c -o google/protobuf/compiler/protobuf_test-parser_unittest.obj `if test -f 'google/protobuf/compiler/parser_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/parser_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/parser_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/$(DEPDIR)/protobuf_test-parser_unittest.Tpo google/protobuf/compiler/$(DEPDIR)/protobuf_test-parser_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/parser_unittest.cc' object='google/protobuf/compiler/protobuf_test-parser_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-parser_unittest.obj `if test -f 'google/protobuf/compiler/parser_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/parser_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/parser_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/protobuf_test-parser_unittest.obj `if test -f 'google/protobuf/compiler/parser_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/parser_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/parser_unittest.cc'; fi` -protobuf_test-cpp_bootstrap_unittest.o: google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-cpp_bootstrap_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Tpo -c -o protobuf_test-cpp_bootstrap_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Tpo $(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc' object='protobuf_test-cpp_bootstrap_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.o: google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.o -MD -MP -MF google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Tpo -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Tpo google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc' object='google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-cpp_bootstrap_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc -protobuf_test-cpp_bootstrap_unittest.obj: google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-cpp_bootstrap_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Tpo -c -o protobuf_test-cpp_bootstrap_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Tpo $(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc' object='protobuf_test-cpp_bootstrap_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.obj: google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.obj -MD -MP -MF google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Tpo -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Tpo google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_bootstrap_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc' object='google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-cpp_bootstrap_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_bootstrap_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc'; fi` -protobuf_test-cpp_unittest.o: google/protobuf/compiler/cpp/cpp_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-cpp_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-cpp_unittest.Tpo -c -o protobuf_test-cpp_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-cpp_unittest.Tpo $(DEPDIR)/protobuf_test-cpp_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_unittest.cc' object='protobuf_test-cpp_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.o: google/protobuf/compiler/cpp/cpp_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.o -MD -MP -MF google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_unittest.Tpo -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_unittest.Tpo google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_unittest.cc' object='google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-cpp_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_unittest.cc -protobuf_test-cpp_unittest.obj: google/protobuf/compiler/cpp/cpp_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-cpp_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-cpp_unittest.Tpo -c -o protobuf_test-cpp_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-cpp_unittest.Tpo $(DEPDIR)/protobuf_test-cpp_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_unittest.cc' object='protobuf_test-cpp_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.obj: google/protobuf/compiler/cpp/cpp_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.obj -MD -MP -MF google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_unittest.Tpo -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_unittest.Tpo google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_unittest.cc' object='google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-cpp_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_unittest.cc'; fi` -protobuf_test-cpp_plugin_unittest.o: google/protobuf/compiler/cpp/cpp_plugin_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-cpp_plugin_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-cpp_plugin_unittest.Tpo -c -o protobuf_test-cpp_plugin_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_plugin_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_plugin_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-cpp_plugin_unittest.Tpo $(DEPDIR)/protobuf_test-cpp_plugin_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_plugin_unittest.cc' object='protobuf_test-cpp_plugin_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.o: google/protobuf/compiler/cpp/cpp_plugin_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.o -MD -MP -MF google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_plugin_unittest.Tpo -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_plugin_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_plugin_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_plugin_unittest.Tpo google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_plugin_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_plugin_unittest.cc' object='google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-cpp_plugin_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_plugin_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_plugin_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.o `test -f 'google/protobuf/compiler/cpp/cpp_plugin_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_plugin_unittest.cc -protobuf_test-cpp_plugin_unittest.obj: google/protobuf/compiler/cpp/cpp_plugin_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-cpp_plugin_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-cpp_plugin_unittest.Tpo -c -o protobuf_test-cpp_plugin_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_plugin_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_plugin_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-cpp_plugin_unittest.Tpo $(DEPDIR)/protobuf_test-cpp_plugin_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_plugin_unittest.cc' object='protobuf_test-cpp_plugin_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.obj: google/protobuf/compiler/cpp/cpp_plugin_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.obj -MD -MP -MF google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_plugin_unittest.Tpo -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_plugin_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_plugin_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_plugin_unittest.Tpo google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_plugin_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_plugin_unittest.cc' object='google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-cpp_plugin_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_plugin_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_plugin_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_plugin_unittest.obj `if test -f 'google/protobuf/compiler/cpp/cpp_plugin_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_plugin_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc'; fi` -protobuf_test-java_plugin_unittest.o: google/protobuf/compiler/java/java_plugin_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-java_plugin_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-java_plugin_unittest.Tpo -c -o protobuf_test-java_plugin_unittest.o `test -f 'google/protobuf/compiler/java/java_plugin_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_plugin_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-java_plugin_unittest.Tpo $(DEPDIR)/protobuf_test-java_plugin_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_plugin_unittest.cc' object='protobuf_test-java_plugin_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.o: google/protobuf/compiler/java/java_plugin_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.o -MD -MP -MF google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_plugin_unittest.Tpo -c -o google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.o `test -f 'google/protobuf/compiler/java/java_plugin_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_plugin_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_plugin_unittest.Tpo google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_plugin_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_plugin_unittest.cc' object='google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-java_plugin_unittest.o `test -f 'google/protobuf/compiler/java/java_plugin_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_plugin_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.o `test -f 'google/protobuf/compiler/java/java_plugin_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_plugin_unittest.cc -protobuf_test-java_plugin_unittest.obj: google/protobuf/compiler/java/java_plugin_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-java_plugin_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-java_plugin_unittest.Tpo -c -o protobuf_test-java_plugin_unittest.obj `if test -f 'google/protobuf/compiler/java/java_plugin_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/java/java_plugin_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/java/java_plugin_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-java_plugin_unittest.Tpo $(DEPDIR)/protobuf_test-java_plugin_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_plugin_unittest.cc' object='protobuf_test-java_plugin_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.obj: google/protobuf/compiler/java/java_plugin_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.obj -MD -MP -MF google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_plugin_unittest.Tpo -c -o google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.obj `if test -f 'google/protobuf/compiler/java/java_plugin_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/java/java_plugin_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/java/java_plugin_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_plugin_unittest.Tpo google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_plugin_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_plugin_unittest.cc' object='google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-java_plugin_unittest.obj `if test -f 'google/protobuf/compiler/java/java_plugin_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/java/java_plugin_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/java/java_plugin_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/java/protobuf_test-java_plugin_unittest.obj `if test -f 'google/protobuf/compiler/java/java_plugin_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/java/java_plugin_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/java/java_plugin_unittest.cc'; fi` -protobuf_test-python_plugin_unittest.o: google/protobuf/compiler/python/python_plugin_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-python_plugin_unittest.o -MD -MP -MF $(DEPDIR)/protobuf_test-python_plugin_unittest.Tpo -c -o protobuf_test-python_plugin_unittest.o `test -f 'google/protobuf/compiler/python/python_plugin_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/python/python_plugin_unittest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-python_plugin_unittest.Tpo $(DEPDIR)/protobuf_test-python_plugin_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/python/python_plugin_unittest.cc' object='protobuf_test-python_plugin_unittest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.o: google/protobuf/compiler/java/java_doc_comment_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.o -MD -MP -MF google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_doc_comment_unittest.Tpo -c -o google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.o `test -f 'google/protobuf/compiler/java/java_doc_comment_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_doc_comment_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_doc_comment_unittest.Tpo google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_doc_comment_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_doc_comment_unittest.cc' object='google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-python_plugin_unittest.o `test -f 'google/protobuf/compiler/python/python_plugin_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/python/python_plugin_unittest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.o `test -f 'google/protobuf/compiler/java/java_doc_comment_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_doc_comment_unittest.cc -protobuf_test-python_plugin_unittest.obj: google/protobuf/compiler/python/python_plugin_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-python_plugin_unittest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-python_plugin_unittest.Tpo -c -o protobuf_test-python_plugin_unittest.obj `if test -f 'google/protobuf/compiler/python/python_plugin_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/python/python_plugin_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/python/python_plugin_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-python_plugin_unittest.Tpo $(DEPDIR)/protobuf_test-python_plugin_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/python/python_plugin_unittest.cc' object='protobuf_test-python_plugin_unittest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.obj: google/protobuf/compiler/java/java_doc_comment_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.obj -MD -MP -MF google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_doc_comment_unittest.Tpo -c -o google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.obj `if test -f 'google/protobuf/compiler/java/java_doc_comment_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/java/java_doc_comment_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/java/java_doc_comment_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_doc_comment_unittest.Tpo google/protobuf/compiler/java/$(DEPDIR)/protobuf_test-java_doc_comment_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/java/java_doc_comment_unittest.cc' object='google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-python_plugin_unittest.obj `if test -f 'google/protobuf/compiler/python/python_plugin_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/python/python_plugin_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/python/python_plugin_unittest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/java/protobuf_test-java_doc_comment_unittest.obj `if test -f 'google/protobuf/compiler/java/java_doc_comment_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/java/java_doc_comment_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/java/java_doc_comment_unittest.cc'; fi` -protobuf_test-test_util.o: google/protobuf/test_util.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-test_util.o -MD -MP -MF $(DEPDIR)/protobuf_test-test_util.Tpo -c -o protobuf_test-test_util.o `test -f 'google/protobuf/test_util.cc' || echo '$(srcdir)/'`google/protobuf/test_util.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-test_util.Tpo $(DEPDIR)/protobuf_test-test_util.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/test_util.cc' object='protobuf_test-test_util.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.o: google/protobuf/compiler/python/python_plugin_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.o -MD -MP -MF google/protobuf/compiler/python/$(DEPDIR)/protobuf_test-python_plugin_unittest.Tpo -c -o google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.o `test -f 'google/protobuf/compiler/python/python_plugin_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/python/python_plugin_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/python/$(DEPDIR)/protobuf_test-python_plugin_unittest.Tpo google/protobuf/compiler/python/$(DEPDIR)/protobuf_test-python_plugin_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/python/python_plugin_unittest.cc' object='google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-test_util.o `test -f 'google/protobuf/test_util.cc' || echo '$(srcdir)/'`google/protobuf/test_util.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.o `test -f 'google/protobuf/compiler/python/python_plugin_unittest.cc' || echo '$(srcdir)/'`google/protobuf/compiler/python/python_plugin_unittest.cc -protobuf_test-test_util.obj: google/protobuf/test_util.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-test_util.obj -MD -MP -MF $(DEPDIR)/protobuf_test-test_util.Tpo -c -o protobuf_test-test_util.obj `if test -f 'google/protobuf/test_util.cc'; then $(CYGPATH_W) 'google/protobuf/test_util.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/test_util.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-test_util.Tpo $(DEPDIR)/protobuf_test-test_util.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/test_util.cc' object='protobuf_test-test_util.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.obj: google/protobuf/compiler/python/python_plugin_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.obj -MD -MP -MF google/protobuf/compiler/python/$(DEPDIR)/protobuf_test-python_plugin_unittest.Tpo -c -o google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.obj `if test -f 'google/protobuf/compiler/python/python_plugin_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/python/python_plugin_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/python/python_plugin_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/python/$(DEPDIR)/protobuf_test-python_plugin_unittest.Tpo google/protobuf/compiler/python/$(DEPDIR)/protobuf_test-python_plugin_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/python/python_plugin_unittest.cc' object='google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-test_util.obj `if test -f 'google/protobuf/test_util.cc'; then $(CYGPATH_W) 'google/protobuf/test_util.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/test_util.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/python/protobuf_test-python_plugin_unittest.obj `if test -f 'google/protobuf/compiler/python/python_plugin_unittest.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/python/python_plugin_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/python/python_plugin_unittest.cc'; fi` -protobuf_test-googletest.o: google/protobuf/testing/googletest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-googletest.o -MD -MP -MF $(DEPDIR)/protobuf_test-googletest.Tpo -c -o protobuf_test-googletest.o `test -f 'google/protobuf/testing/googletest.cc' || echo '$(srcdir)/'`google/protobuf/testing/googletest.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-googletest.Tpo $(DEPDIR)/protobuf_test-googletest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/googletest.cc' object='protobuf_test-googletest.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-test_util.o: google/protobuf/test_util.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-test_util.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-test_util.Tpo -c -o google/protobuf/protobuf_test-test_util.o `test -f 'google/protobuf/test_util.cc' || echo '$(srcdir)/'`google/protobuf/test_util.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-test_util.Tpo google/protobuf/$(DEPDIR)/protobuf_test-test_util.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/test_util.cc' object='google/protobuf/protobuf_test-test_util.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-googletest.o `test -f 'google/protobuf/testing/googletest.cc' || echo '$(srcdir)/'`google/protobuf/testing/googletest.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-test_util.o `test -f 'google/protobuf/test_util.cc' || echo '$(srcdir)/'`google/protobuf/test_util.cc -protobuf_test-googletest.obj: google/protobuf/testing/googletest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-googletest.obj -MD -MP -MF $(DEPDIR)/protobuf_test-googletest.Tpo -c -o protobuf_test-googletest.obj `if test -f 'google/protobuf/testing/googletest.cc'; then $(CYGPATH_W) 'google/protobuf/testing/googletest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/googletest.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-googletest.Tpo $(DEPDIR)/protobuf_test-googletest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/googletest.cc' object='protobuf_test-googletest.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-test_util.obj: google/protobuf/test_util.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-test_util.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-test_util.Tpo -c -o google/protobuf/protobuf_test-test_util.obj `if test -f 'google/protobuf/test_util.cc'; then $(CYGPATH_W) 'google/protobuf/test_util.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/test_util.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-test_util.Tpo google/protobuf/$(DEPDIR)/protobuf_test-test_util.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/test_util.cc' object='google/protobuf/protobuf_test-test_util.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-googletest.obj `if test -f 'google/protobuf/testing/googletest.cc'; then $(CYGPATH_W) 'google/protobuf/testing/googletest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/googletest.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-test_util.obj `if test -f 'google/protobuf/test_util.cc'; then $(CYGPATH_W) 'google/protobuf/test_util.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/test_util.cc'; fi` -protobuf_test-file.o: google/protobuf/testing/file.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-file.o -MD -MP -MF $(DEPDIR)/protobuf_test-file.Tpo -c -o protobuf_test-file.o `test -f 'google/protobuf/testing/file.cc' || echo '$(srcdir)/'`google/protobuf/testing/file.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-file.Tpo $(DEPDIR)/protobuf_test-file.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/file.cc' object='protobuf_test-file.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/testing/protobuf_test-googletest.o: google/protobuf/testing/googletest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/testing/protobuf_test-googletest.o -MD -MP -MF google/protobuf/testing/$(DEPDIR)/protobuf_test-googletest.Tpo -c -o google/protobuf/testing/protobuf_test-googletest.o `test -f 'google/protobuf/testing/googletest.cc' || echo '$(srcdir)/'`google/protobuf/testing/googletest.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/testing/$(DEPDIR)/protobuf_test-googletest.Tpo google/protobuf/testing/$(DEPDIR)/protobuf_test-googletest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/googletest.cc' object='google/protobuf/testing/protobuf_test-googletest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-file.o `test -f 'google/protobuf/testing/file.cc' || echo '$(srcdir)/'`google/protobuf/testing/file.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/testing/protobuf_test-googletest.o `test -f 'google/protobuf/testing/googletest.cc' || echo '$(srcdir)/'`google/protobuf/testing/googletest.cc -protobuf_test-file.obj: google/protobuf/testing/file.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-file.obj -MD -MP -MF $(DEPDIR)/protobuf_test-file.Tpo -c -o protobuf_test-file.obj `if test -f 'google/protobuf/testing/file.cc'; then $(CYGPATH_W) 'google/protobuf/testing/file.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/file.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-file.Tpo $(DEPDIR)/protobuf_test-file.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/file.cc' object='protobuf_test-file.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/testing/protobuf_test-googletest.obj: google/protobuf/testing/googletest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/testing/protobuf_test-googletest.obj -MD -MP -MF google/protobuf/testing/$(DEPDIR)/protobuf_test-googletest.Tpo -c -o google/protobuf/testing/protobuf_test-googletest.obj `if test -f 'google/protobuf/testing/googletest.cc'; then $(CYGPATH_W) 'google/protobuf/testing/googletest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/googletest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/testing/$(DEPDIR)/protobuf_test-googletest.Tpo google/protobuf/testing/$(DEPDIR)/protobuf_test-googletest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/googletest.cc' object='google/protobuf/testing/protobuf_test-googletest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-file.obj `if test -f 'google/protobuf/testing/file.cc'; then $(CYGPATH_W) 'google/protobuf/testing/file.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/file.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/testing/protobuf_test-googletest.obj `if test -f 'google/protobuf/testing/googletest.cc'; then $(CYGPATH_W) 'google/protobuf/testing/googletest.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/googletest.cc'; fi` -protobuf_test-unittest_lite.pb.o: google/protobuf/unittest_lite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_lite.pb.o -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_lite.pb.Tpo -c -o protobuf_test-unittest_lite.pb.o `test -f 'google/protobuf/unittest_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_lite.pb.Tpo $(DEPDIR)/protobuf_test-unittest_lite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite.pb.cc' object='protobuf_test-unittest_lite.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/testing/protobuf_test-file.o: google/protobuf/testing/file.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/testing/protobuf_test-file.o -MD -MP -MF google/protobuf/testing/$(DEPDIR)/protobuf_test-file.Tpo -c -o google/protobuf/testing/protobuf_test-file.o `test -f 'google/protobuf/testing/file.cc' || echo '$(srcdir)/'`google/protobuf/testing/file.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/testing/$(DEPDIR)/protobuf_test-file.Tpo google/protobuf/testing/$(DEPDIR)/protobuf_test-file.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/file.cc' object='google/protobuf/testing/protobuf_test-file.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_lite.pb.o `test -f 'google/protobuf/unittest_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/testing/protobuf_test-file.o `test -f 'google/protobuf/testing/file.cc' || echo '$(srcdir)/'`google/protobuf/testing/file.cc -protobuf_test-unittest_lite.pb.obj: google/protobuf/unittest_lite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_lite.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_lite.pb.Tpo -c -o protobuf_test-unittest_lite.pb.obj `if test -f 'google/protobuf/unittest_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_lite.pb.Tpo $(DEPDIR)/protobuf_test-unittest_lite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite.pb.cc' object='protobuf_test-unittest_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/testing/protobuf_test-file.obj: google/protobuf/testing/file.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/testing/protobuf_test-file.obj -MD -MP -MF google/protobuf/testing/$(DEPDIR)/protobuf_test-file.Tpo -c -o google/protobuf/testing/protobuf_test-file.obj `if test -f 'google/protobuf/testing/file.cc'; then $(CYGPATH_W) 'google/protobuf/testing/file.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/file.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/testing/$(DEPDIR)/protobuf_test-file.Tpo google/protobuf/testing/$(DEPDIR)/protobuf_test-file.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/file.cc' object='google/protobuf/testing/protobuf_test-file.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_lite.pb.obj `if test -f 'google/protobuf/unittest_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/testing/protobuf_test-file.obj `if test -f 'google/protobuf/testing/file.cc'; then $(CYGPATH_W) 'google/protobuf/testing/file.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/file.cc'; fi` -protobuf_test-unittest_import_lite.pb.o: google/protobuf/unittest_import_lite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_import_lite.pb.o -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_import_lite.pb.Tpo -c -o protobuf_test-unittest_import_lite.pb.o `test -f 'google/protobuf/unittest_import_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_lite.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_import_lite.pb.Tpo $(DEPDIR)/protobuf_test-unittest_import_lite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_lite.pb.cc' object='protobuf_test-unittest_import_lite.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_lite.pb.o: google/protobuf/unittest_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_lite.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_lite.pb.o `test -f 'google/protobuf/unittest_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite.pb.cc' object='google/protobuf/protobuf_test-unittest_lite.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_import_lite.pb.o `test -f 'google/protobuf/unittest_import_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_lite.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_lite.pb.o `test -f 'google/protobuf/unittest_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite.pb.cc -protobuf_test-unittest_import_lite.pb.obj: google/protobuf/unittest_import_lite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_import_lite.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_import_lite.pb.Tpo -c -o protobuf_test-unittest_import_lite.pb.obj `if test -f 'google/protobuf/unittest_import_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_lite.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_import_lite.pb.Tpo $(DEPDIR)/protobuf_test-unittest_import_lite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_lite.pb.cc' object='protobuf_test-unittest_import_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_lite.pb.obj: google/protobuf/unittest_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_lite.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_lite.pb.obj `if test -f 'google/protobuf/unittest_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite.pb.cc' object='google/protobuf/protobuf_test-unittest_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_import_lite.pb.obj `if test -f 'google/protobuf/unittest_import_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_lite.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_lite.pb.obj `if test -f 'google/protobuf/unittest_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite.pb.cc'; fi` -protobuf_test-unittest.pb.o: google/protobuf/unittest.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest.pb.o -MD -MP -MF $(DEPDIR)/protobuf_test-unittest.pb.Tpo -c -o protobuf_test-unittest.pb.o `test -f 'google/protobuf/unittest.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest.pb.Tpo $(DEPDIR)/protobuf_test-unittest.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest.pb.cc' object='protobuf_test-unittest.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_import_lite.pb.o: google/protobuf/unittest_import_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_import_lite.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_lite.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_import_lite.pb.o `test -f 'google/protobuf/unittest_import_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_lite.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_lite.pb.cc' object='google/protobuf/protobuf_test-unittest_import_lite.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest.pb.o `test -f 'google/protobuf/unittest.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_import_lite.pb.o `test -f 'google/protobuf/unittest_import_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_lite.pb.cc -protobuf_test-unittest.pb.obj: google/protobuf/unittest.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_test-unittest.pb.Tpo -c -o protobuf_test-unittest.pb.obj `if test -f 'google/protobuf/unittest.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest.pb.Tpo $(DEPDIR)/protobuf_test-unittest.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest.pb.cc' object='protobuf_test-unittest.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_import_lite.pb.obj: google/protobuf/unittest_import_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_import_lite.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_lite.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_import_lite.pb.obj `if test -f 'google/protobuf/unittest_import_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_lite.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_lite.pb.cc' object='google/protobuf/protobuf_test-unittest_import_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest.pb.obj `if test -f 'google/protobuf/unittest.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_import_lite.pb.obj `if test -f 'google/protobuf/unittest_import_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_lite.pb.cc'; fi` -protobuf_test-unittest_empty.pb.o: google/protobuf/unittest_empty.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_empty.pb.o -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_empty.pb.Tpo -c -o protobuf_test-unittest_empty.pb.o `test -f 'google/protobuf/unittest_empty.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_empty.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_empty.pb.Tpo $(DEPDIR)/protobuf_test-unittest_empty.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_empty.pb.cc' object='protobuf_test-unittest_empty.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_import_public_lite.pb.o: google/protobuf/unittest_import_public_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_import_public_lite.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public_lite.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_import_public_lite.pb.o `test -f 'google/protobuf/unittest_import_public_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_public_lite.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_public_lite.pb.cc' object='google/protobuf/protobuf_test-unittest_import_public_lite.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_empty.pb.o `test -f 'google/protobuf/unittest_empty.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_empty.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_import_public_lite.pb.o `test -f 'google/protobuf/unittest_import_public_lite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_public_lite.pb.cc -protobuf_test-unittest_empty.pb.obj: google/protobuf/unittest_empty.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_empty.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_empty.pb.Tpo -c -o protobuf_test-unittest_empty.pb.obj `if test -f 'google/protobuf/unittest_empty.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_empty.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_empty.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_empty.pb.Tpo $(DEPDIR)/protobuf_test-unittest_empty.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_empty.pb.cc' object='protobuf_test-unittest_empty.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_import_public_lite.pb.obj: google/protobuf/unittest_import_public_lite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_import_public_lite.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public_lite.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_import_public_lite.pb.obj `if test -f 'google/protobuf/unittest_import_public_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_public_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_public_lite.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public_lite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public_lite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_public_lite.pb.cc' object='google/protobuf/protobuf_test-unittest_import_public_lite.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_empty.pb.obj `if test -f 'google/protobuf/unittest_empty.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_empty.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_empty.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_import_public_lite.pb.obj `if test -f 'google/protobuf/unittest_import_public_lite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_public_lite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_public_lite.pb.cc'; fi` -protobuf_test-unittest_import.pb.o: google/protobuf/unittest_import.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_import.pb.o -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_import.pb.Tpo -c -o protobuf_test-unittest_import.pb.o `test -f 'google/protobuf/unittest_import.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_import.pb.Tpo $(DEPDIR)/protobuf_test-unittest_import.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import.pb.cc' object='protobuf_test-unittest_import.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest.pb.o: google/protobuf/unittest.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest.pb.Tpo -c -o google/protobuf/protobuf_test-unittest.pb.o `test -f 'google/protobuf/unittest.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest.pb.cc' object='google/protobuf/protobuf_test-unittest.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_import.pb.o `test -f 'google/protobuf/unittest_import.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest.pb.o `test -f 'google/protobuf/unittest.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest.pb.cc -protobuf_test-unittest_import.pb.obj: google/protobuf/unittest_import.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_import.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_import.pb.Tpo -c -o protobuf_test-unittest_import.pb.obj `if test -f 'google/protobuf/unittest_import.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_import.pb.Tpo $(DEPDIR)/protobuf_test-unittest_import.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import.pb.cc' object='protobuf_test-unittest_import.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest.pb.obj: google/protobuf/unittest.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest.pb.Tpo -c -o google/protobuf/protobuf_test-unittest.pb.obj `if test -f 'google/protobuf/unittest.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest.pb.cc' object='google/protobuf/protobuf_test-unittest.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_import.pb.obj `if test -f 'google/protobuf/unittest_import.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest.pb.obj `if test -f 'google/protobuf/unittest.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest.pb.cc'; fi` -protobuf_test-unittest_mset.pb.o: google/protobuf/unittest_mset.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_mset.pb.o -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_mset.pb.Tpo -c -o protobuf_test-unittest_mset.pb.o `test -f 'google/protobuf/unittest_mset.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_mset.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_mset.pb.Tpo $(DEPDIR)/protobuf_test-unittest_mset.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_mset.pb.cc' object='protobuf_test-unittest_mset.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_empty.pb.o: google/protobuf/unittest_empty.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_empty.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_empty.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_empty.pb.o `test -f 'google/protobuf/unittest_empty.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_empty.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_empty.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_empty.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_empty.pb.cc' object='google/protobuf/protobuf_test-unittest_empty.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_mset.pb.o `test -f 'google/protobuf/unittest_mset.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_mset.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_empty.pb.o `test -f 'google/protobuf/unittest_empty.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_empty.pb.cc -protobuf_test-unittest_mset.pb.obj: google/protobuf/unittest_mset.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_mset.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_mset.pb.Tpo -c -o protobuf_test-unittest_mset.pb.obj `if test -f 'google/protobuf/unittest_mset.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_mset.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_mset.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_mset.pb.Tpo $(DEPDIR)/protobuf_test-unittest_mset.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_mset.pb.cc' object='protobuf_test-unittest_mset.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_empty.pb.obj: google/protobuf/unittest_empty.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_empty.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_empty.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_empty.pb.obj `if test -f 'google/protobuf/unittest_empty.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_empty.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_empty.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_empty.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_empty.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_empty.pb.cc' object='google/protobuf/protobuf_test-unittest_empty.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_mset.pb.obj `if test -f 'google/protobuf/unittest_mset.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_mset.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_mset.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_empty.pb.obj `if test -f 'google/protobuf/unittest_empty.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_empty.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_empty.pb.cc'; fi` -protobuf_test-unittest_optimize_for.pb.o: google/protobuf/unittest_optimize_for.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_optimize_for.pb.o -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Tpo -c -o protobuf_test-unittest_optimize_for.pb.o `test -f 'google/protobuf/unittest_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_optimize_for.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Tpo $(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_optimize_for.pb.cc' object='protobuf_test-unittest_optimize_for.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_import.pb.o: google/protobuf/unittest_import.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_import.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_import.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_import.pb.o `test -f 'google/protobuf/unittest_import.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_import.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_import.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import.pb.cc' object='google/protobuf/protobuf_test-unittest_import.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_optimize_for.pb.o `test -f 'google/protobuf/unittest_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_optimize_for.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_import.pb.o `test -f 'google/protobuf/unittest_import.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import.pb.cc -protobuf_test-unittest_optimize_for.pb.obj: google/protobuf/unittest_optimize_for.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_optimize_for.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Tpo -c -o protobuf_test-unittest_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_optimize_for.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Tpo $(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_optimize_for.pb.cc' object='protobuf_test-unittest_optimize_for.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_import.pb.obj: google/protobuf/unittest_import.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_import.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_import.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_import.pb.obj `if test -f 'google/protobuf/unittest_import.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_import.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_import.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import.pb.cc' object='google/protobuf/protobuf_test-unittest_import.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_optimize_for.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_import.pb.obj `if test -f 'google/protobuf/unittest_import.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import.pb.cc'; fi` -protobuf_test-unittest_embed_optimize_for.pb.o: google/protobuf/unittest_embed_optimize_for.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_embed_optimize_for.pb.o -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Tpo -c -o protobuf_test-unittest_embed_optimize_for.pb.o `test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_embed_optimize_for.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Tpo $(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_embed_optimize_for.pb.cc' object='protobuf_test-unittest_embed_optimize_for.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_import_public.pb.o: google/protobuf/unittest_import_public.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_import_public.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_import_public.pb.o `test -f 'google/protobuf/unittest_import_public.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_public.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_public.pb.cc' object='google/protobuf/protobuf_test-unittest_import_public.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_embed_optimize_for.pb.o `test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_embed_optimize_for.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_import_public.pb.o `test -f 'google/protobuf/unittest_import_public.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_import_public.pb.cc -protobuf_test-unittest_embed_optimize_for.pb.obj: google/protobuf/unittest_embed_optimize_for.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_embed_optimize_for.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Tpo -c -o protobuf_test-unittest_embed_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_embed_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_embed_optimize_for.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Tpo $(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_embed_optimize_for.pb.cc' object='protobuf_test-unittest_embed_optimize_for.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_import_public.pb.obj: google/protobuf/unittest_import_public.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_import_public.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_import_public.pb.obj `if test -f 'google/protobuf/unittest_import_public.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_public.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_public.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_import_public.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_import_public.pb.cc' object='google/protobuf/protobuf_test-unittest_import_public.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_embed_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_embed_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_embed_optimize_for.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_import_public.pb.obj `if test -f 'google/protobuf/unittest_import_public.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_import_public.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_import_public.pb.cc'; fi` -protobuf_test-unittest_custom_options.pb.o: google/protobuf/unittest_custom_options.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_custom_options.pb.o -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_custom_options.pb.Tpo -c -o protobuf_test-unittest_custom_options.pb.o `test -f 'google/protobuf/unittest_custom_options.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_custom_options.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_custom_options.pb.Tpo $(DEPDIR)/protobuf_test-unittest_custom_options.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_custom_options.pb.cc' object='protobuf_test-unittest_custom_options.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_mset.pb.o: google/protobuf/unittest_mset.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_mset.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_mset.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_mset.pb.o `test -f 'google/protobuf/unittest_mset.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_mset.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_mset.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_mset.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_mset.pb.cc' object='google/protobuf/protobuf_test-unittest_mset.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_custom_options.pb.o `test -f 'google/protobuf/unittest_custom_options.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_custom_options.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_mset.pb.o `test -f 'google/protobuf/unittest_mset.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_mset.pb.cc -protobuf_test-unittest_custom_options.pb.obj: google/protobuf/unittest_custom_options.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_custom_options.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_custom_options.pb.Tpo -c -o protobuf_test-unittest_custom_options.pb.obj `if test -f 'google/protobuf/unittest_custom_options.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_custom_options.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_custom_options.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_custom_options.pb.Tpo $(DEPDIR)/protobuf_test-unittest_custom_options.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_custom_options.pb.cc' object='protobuf_test-unittest_custom_options.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_mset.pb.obj: google/protobuf/unittest_mset.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_mset.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_mset.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_mset.pb.obj `if test -f 'google/protobuf/unittest_mset.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_mset.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_mset.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_mset.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_mset.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_mset.pb.cc' object='google/protobuf/protobuf_test-unittest_mset.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_custom_options.pb.obj `if test -f 'google/protobuf/unittest_custom_options.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_custom_options.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_custom_options.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_mset.pb.obj `if test -f 'google/protobuf/unittest_mset.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_mset.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_mset.pb.cc'; fi` -protobuf_test-unittest_lite_imports_nonlite.pb.o: google/protobuf/unittest_lite_imports_nonlite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_lite_imports_nonlite.pb.o -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Tpo -c -o protobuf_test-unittest_lite_imports_nonlite.pb.o `test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite_imports_nonlite.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Tpo $(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite_imports_nonlite.pb.cc' object='protobuf_test-unittest_lite_imports_nonlite.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_optimize_for.pb.o: google/protobuf/unittest_optimize_for.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_optimize_for.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_optimize_for.pb.o `test -f 'google/protobuf/unittest_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_optimize_for.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_optimize_for.pb.cc' object='google/protobuf/protobuf_test-unittest_optimize_for.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_lite_imports_nonlite.pb.o `test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite_imports_nonlite.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_optimize_for.pb.o `test -f 'google/protobuf/unittest_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_optimize_for.pb.cc -protobuf_test-unittest_lite_imports_nonlite.pb.obj: google/protobuf/unittest_lite_imports_nonlite.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_lite_imports_nonlite.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Tpo -c -o protobuf_test-unittest_lite_imports_nonlite.pb.obj `if test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite_imports_nonlite.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Tpo $(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite_imports_nonlite.pb.cc' object='protobuf_test-unittest_lite_imports_nonlite.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_optimize_for.pb.obj: google/protobuf/unittest_optimize_for.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_optimize_for.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_optimize_for.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_optimize_for.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_optimize_for.pb.cc' object='google/protobuf/protobuf_test-unittest_optimize_for.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_lite_imports_nonlite.pb.obj `if test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite_imports_nonlite.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_optimize_for.pb.cc'; fi` -protobuf_test-unittest_no_generic_services.pb.o: google/protobuf/unittest_no_generic_services.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_no_generic_services.pb.o -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Tpo -c -o protobuf_test-unittest_no_generic_services.pb.o `test -f 'google/protobuf/unittest_no_generic_services.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_no_generic_services.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Tpo $(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_no_generic_services.pb.cc' object='protobuf_test-unittest_no_generic_services.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.o: google/protobuf/unittest_embed_optimize_for.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.o `test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_embed_optimize_for.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_embed_optimize_for.pb.cc' object='google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_no_generic_services.pb.o `test -f 'google/protobuf/unittest_no_generic_services.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_no_generic_services.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.o `test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_embed_optimize_for.pb.cc -protobuf_test-unittest_no_generic_services.pb.obj: google/protobuf/unittest_no_generic_services.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-unittest_no_generic_services.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Tpo -c -o protobuf_test-unittest_no_generic_services.pb.obj `if test -f 'google/protobuf/unittest_no_generic_services.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_no_generic_services.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_no_generic_services.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Tpo $(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_no_generic_services.pb.cc' object='protobuf_test-unittest_no_generic_services.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.obj: google/protobuf/unittest_embed_optimize_for.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_embed_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_embed_optimize_for.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_embed_optimize_for.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_embed_optimize_for.pb.cc' object='google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-unittest_no_generic_services.pb.obj `if test -f 'google/protobuf/unittest_no_generic_services.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_no_generic_services.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_no_generic_services.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_embed_optimize_for.pb.obj `if test -f 'google/protobuf/unittest_embed_optimize_for.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_embed_optimize_for.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_embed_optimize_for.pb.cc'; fi` -protobuf_test-cpp_test_bad_identifiers.pb.o: google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-cpp_test_bad_identifiers.pb.o -MD -MP -MF $(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Tpo -c -o protobuf_test-cpp_test_bad_identifiers.pb.o `test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Tpo $(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' object='protobuf_test-cpp_test_bad_identifiers.pb.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_custom_options.pb.o: google/protobuf/unittest_custom_options.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_custom_options.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_custom_options.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_custom_options.pb.o `test -f 'google/protobuf/unittest_custom_options.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_custom_options.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_custom_options.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_custom_options.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_custom_options.pb.cc' object='google/protobuf/protobuf_test-unittest_custom_options.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-cpp_test_bad_identifiers.pb.o `test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_custom_options.pb.o `test -f 'google/protobuf/unittest_custom_options.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_custom_options.pb.cc -protobuf_test-cpp_test_bad_identifiers.pb.obj: google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT protobuf_test-cpp_test_bad_identifiers.pb.obj -MD -MP -MF $(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Tpo -c -o protobuf_test-cpp_test_bad_identifiers.pb.obj `if test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Tpo $(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' object='protobuf_test-cpp_test_bad_identifiers.pb.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_custom_options.pb.obj: google/protobuf/unittest_custom_options.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_custom_options.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_custom_options.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_custom_options.pb.obj `if test -f 'google/protobuf/unittest_custom_options.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_custom_options.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_custom_options.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_custom_options.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_custom_options.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_custom_options.pb.cc' object='google/protobuf/protobuf_test-unittest_custom_options.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o protobuf_test-cpp_test_bad_identifiers.pb.obj `if test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_custom_options.pb.obj `if test -f 'google/protobuf/unittest_custom_options.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_custom_options.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_custom_options.pb.cc'; fi` -main.o: google/protobuf/compiler/main.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT main.o -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.o `test -f 'google/protobuf/compiler/main.cc' || echo '$(srcdir)/'`google/protobuf/compiler/main.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/main.cc' object='main.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.o: google/protobuf/unittest_lite_imports_nonlite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.o `test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite_imports_nonlite.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite_imports_nonlite.pb.cc' object='google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o main.o `test -f 'google/protobuf/compiler/main.cc' || echo '$(srcdir)/'`google/protobuf/compiler/main.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.o `test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_lite_imports_nonlite.pb.cc -main.obj: google/protobuf/compiler/main.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT main.obj -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.obj `if test -f 'google/protobuf/compiler/main.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/main.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/main.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/main.cc' object='main.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.obj: google/protobuf/unittest_lite_imports_nonlite.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.obj `if test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite_imports_nonlite.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_lite_imports_nonlite.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_lite_imports_nonlite.pb.cc' object='google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o main.obj `if test -f 'google/protobuf/compiler/main.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/main.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/main.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_lite_imports_nonlite.pb.obj `if test -f 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_lite_imports_nonlite.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_lite_imports_nonlite.pb.cc'; fi` -test_plugin-mock_code_generator.o: google/protobuf/compiler/mock_code_generator.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_plugin-mock_code_generator.o -MD -MP -MF $(DEPDIR)/test_plugin-mock_code_generator.Tpo -c -o test_plugin-mock_code_generator.o `test -f 'google/protobuf/compiler/mock_code_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/mock_code_generator.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/test_plugin-mock_code_generator.Tpo $(DEPDIR)/test_plugin-mock_code_generator.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/mock_code_generator.cc' object='test_plugin-mock_code_generator.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_no_generic_services.pb.o: google/protobuf/unittest_no_generic_services.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_no_generic_services.pb.o -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_no_generic_services.pb.o `test -f 'google/protobuf/unittest_no_generic_services.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_no_generic_services.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_no_generic_services.pb.cc' object='google/protobuf/protobuf_test-unittest_no_generic_services.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_plugin-mock_code_generator.o `test -f 'google/protobuf/compiler/mock_code_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/mock_code_generator.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_no_generic_services.pb.o `test -f 'google/protobuf/unittest_no_generic_services.pb.cc' || echo '$(srcdir)/'`google/protobuf/unittest_no_generic_services.pb.cc -test_plugin-mock_code_generator.obj: google/protobuf/compiler/mock_code_generator.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_plugin-mock_code_generator.obj -MD -MP -MF $(DEPDIR)/test_plugin-mock_code_generator.Tpo -c -o test_plugin-mock_code_generator.obj `if test -f 'google/protobuf/compiler/mock_code_generator.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/mock_code_generator.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/mock_code_generator.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/test_plugin-mock_code_generator.Tpo $(DEPDIR)/test_plugin-mock_code_generator.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/mock_code_generator.cc' object='test_plugin-mock_code_generator.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/protobuf_test-unittest_no_generic_services.pb.obj: google/protobuf/unittest_no_generic_services.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/protobuf_test-unittest_no_generic_services.pb.obj -MD -MP -MF google/protobuf/$(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Tpo -c -o google/protobuf/protobuf_test-unittest_no_generic_services.pb.obj `if test -f 'google/protobuf/unittest_no_generic_services.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_no_generic_services.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_no_generic_services.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/$(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Tpo google/protobuf/$(DEPDIR)/protobuf_test-unittest_no_generic_services.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/unittest_no_generic_services.pb.cc' object='google/protobuf/protobuf_test-unittest_no_generic_services.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_plugin-mock_code_generator.obj `if test -f 'google/protobuf/compiler/mock_code_generator.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/mock_code_generator.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/mock_code_generator.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/protobuf_test-unittest_no_generic_services.pb.obj `if test -f 'google/protobuf/unittest_no_generic_services.pb.cc'; then $(CYGPATH_W) 'google/protobuf/unittest_no_generic_services.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/unittest_no_generic_services.pb.cc'; fi` -test_plugin-file.o: google/protobuf/testing/file.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_plugin-file.o -MD -MP -MF $(DEPDIR)/test_plugin-file.Tpo -c -o test_plugin-file.o `test -f 'google/protobuf/testing/file.cc' || echo '$(srcdir)/'`google/protobuf/testing/file.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/test_plugin-file.Tpo $(DEPDIR)/test_plugin-file.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/file.cc' object='test_plugin-file.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.o: google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.o -MD -MP -MF google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Tpo -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.o `test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Tpo google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' object='google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_plugin-file.o `test -f 'google/protobuf/testing/file.cc' || echo '$(srcdir)/'`google/protobuf/testing/file.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.o `test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' || echo '$(srcdir)/'`google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc -test_plugin-file.obj: google/protobuf/testing/file.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_plugin-file.obj -MD -MP -MF $(DEPDIR)/test_plugin-file.Tpo -c -o test_plugin-file.obj `if test -f 'google/protobuf/testing/file.cc'; then $(CYGPATH_W) 'google/protobuf/testing/file.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/file.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/test_plugin-file.Tpo $(DEPDIR)/test_plugin-file.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/file.cc' object='test_plugin-file.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.obj: google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.obj -MD -MP -MF google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Tpo -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.obj `if test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Tpo google/protobuf/compiler/cpp/$(DEPDIR)/protobuf_test-cpp_test_bad_identifiers.pb.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc' object='google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_plugin-file.obj `if test -f 'google/protobuf/testing/file.cc'; then $(CYGPATH_W) 'google/protobuf/testing/file.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/file.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(protobuf_test_CPPFLAGS) $(CPPFLAGS) $(protobuf_test_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/cpp/protobuf_test-cpp_test_bad_identifiers.pb.obj `if test -f 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc'; fi` -test_plugin-test_plugin.o: google/protobuf/compiler/test_plugin.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_plugin-test_plugin.o -MD -MP -MF $(DEPDIR)/test_plugin-test_plugin.Tpo -c -o test_plugin-test_plugin.o `test -f 'google/protobuf/compiler/test_plugin.cc' || echo '$(srcdir)/'`google/protobuf/compiler/test_plugin.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/test_plugin-test_plugin.Tpo $(DEPDIR)/test_plugin-test_plugin.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/test_plugin.cc' object='test_plugin-test_plugin.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/test_plugin-mock_code_generator.o: google/protobuf/compiler/mock_code_generator.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/test_plugin-mock_code_generator.o -MD -MP -MF google/protobuf/compiler/$(DEPDIR)/test_plugin-mock_code_generator.Tpo -c -o google/protobuf/compiler/test_plugin-mock_code_generator.o `test -f 'google/protobuf/compiler/mock_code_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/mock_code_generator.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/$(DEPDIR)/test_plugin-mock_code_generator.Tpo google/protobuf/compiler/$(DEPDIR)/test_plugin-mock_code_generator.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/mock_code_generator.cc' object='google/protobuf/compiler/test_plugin-mock_code_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_plugin-test_plugin.o `test -f 'google/protobuf/compiler/test_plugin.cc' || echo '$(srcdir)/'`google/protobuf/compiler/test_plugin.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/test_plugin-mock_code_generator.o `test -f 'google/protobuf/compiler/mock_code_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/mock_code_generator.cc -test_plugin-test_plugin.obj: google/protobuf/compiler/test_plugin.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_plugin-test_plugin.obj -MD -MP -MF $(DEPDIR)/test_plugin-test_plugin.Tpo -c -o test_plugin-test_plugin.obj `if test -f 'google/protobuf/compiler/test_plugin.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/test_plugin.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/test_plugin.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/test_plugin-test_plugin.Tpo $(DEPDIR)/test_plugin-test_plugin.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/test_plugin.cc' object='test_plugin-test_plugin.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/test_plugin-mock_code_generator.obj: google/protobuf/compiler/mock_code_generator.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/test_plugin-mock_code_generator.obj -MD -MP -MF google/protobuf/compiler/$(DEPDIR)/test_plugin-mock_code_generator.Tpo -c -o google/protobuf/compiler/test_plugin-mock_code_generator.obj `if test -f 'google/protobuf/compiler/mock_code_generator.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/mock_code_generator.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/mock_code_generator.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/$(DEPDIR)/test_plugin-mock_code_generator.Tpo google/protobuf/compiler/$(DEPDIR)/test_plugin-mock_code_generator.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/mock_code_generator.cc' object='google/protobuf/compiler/test_plugin-mock_code_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_plugin-test_plugin.obj `if test -f 'google/protobuf/compiler/test_plugin.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/test_plugin.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/test_plugin.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/test_plugin-mock_code_generator.obj `if test -f 'google/protobuf/compiler/mock_code_generator.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/mock_code_generator.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/mock_code_generator.cc'; fi` -zcgunzip.o: google/protobuf/testing/zcgunzip.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zcgunzip.o -MD -MP -MF $(DEPDIR)/zcgunzip.Tpo -c -o zcgunzip.o `test -f 'google/protobuf/testing/zcgunzip.cc' || echo '$(srcdir)/'`google/protobuf/testing/zcgunzip.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/zcgunzip.Tpo $(DEPDIR)/zcgunzip.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/zcgunzip.cc' object='zcgunzip.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/testing/test_plugin-file.o: google/protobuf/testing/file.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/testing/test_plugin-file.o -MD -MP -MF google/protobuf/testing/$(DEPDIR)/test_plugin-file.Tpo -c -o google/protobuf/testing/test_plugin-file.o `test -f 'google/protobuf/testing/file.cc' || echo '$(srcdir)/'`google/protobuf/testing/file.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/testing/$(DEPDIR)/test_plugin-file.Tpo google/protobuf/testing/$(DEPDIR)/test_plugin-file.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/file.cc' object='google/protobuf/testing/test_plugin-file.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zcgunzip.o `test -f 'google/protobuf/testing/zcgunzip.cc' || echo '$(srcdir)/'`google/protobuf/testing/zcgunzip.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/testing/test_plugin-file.o `test -f 'google/protobuf/testing/file.cc' || echo '$(srcdir)/'`google/protobuf/testing/file.cc -zcgunzip.obj: google/protobuf/testing/zcgunzip.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zcgunzip.obj -MD -MP -MF $(DEPDIR)/zcgunzip.Tpo -c -o zcgunzip.obj `if test -f 'google/protobuf/testing/zcgunzip.cc'; then $(CYGPATH_W) 'google/protobuf/testing/zcgunzip.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/zcgunzip.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/zcgunzip.Tpo $(DEPDIR)/zcgunzip.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/zcgunzip.cc' object='zcgunzip.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/testing/test_plugin-file.obj: google/protobuf/testing/file.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/testing/test_plugin-file.obj -MD -MP -MF google/protobuf/testing/$(DEPDIR)/test_plugin-file.Tpo -c -o google/protobuf/testing/test_plugin-file.obj `if test -f 'google/protobuf/testing/file.cc'; then $(CYGPATH_W) 'google/protobuf/testing/file.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/file.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/testing/$(DEPDIR)/test_plugin-file.Tpo google/protobuf/testing/$(DEPDIR)/test_plugin-file.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/file.cc' object='google/protobuf/testing/test_plugin-file.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zcgunzip.obj `if test -f 'google/protobuf/testing/zcgunzip.cc'; then $(CYGPATH_W) 'google/protobuf/testing/zcgunzip.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/zcgunzip.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/testing/test_plugin-file.obj `if test -f 'google/protobuf/testing/file.cc'; then $(CYGPATH_W) 'google/protobuf/testing/file.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/file.cc'; fi` -zcgzip.o: google/protobuf/testing/zcgzip.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zcgzip.o -MD -MP -MF $(DEPDIR)/zcgzip.Tpo -c -o zcgzip.o `test -f 'google/protobuf/testing/zcgzip.cc' || echo '$(srcdir)/'`google/protobuf/testing/zcgzip.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/zcgzip.Tpo $(DEPDIR)/zcgzip.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/zcgzip.cc' object='zcgzip.o' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/test_plugin-test_plugin.o: google/protobuf/compiler/test_plugin.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/test_plugin-test_plugin.o -MD -MP -MF google/protobuf/compiler/$(DEPDIR)/test_plugin-test_plugin.Tpo -c -o google/protobuf/compiler/test_plugin-test_plugin.o `test -f 'google/protobuf/compiler/test_plugin.cc' || echo '$(srcdir)/'`google/protobuf/compiler/test_plugin.cc +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/$(DEPDIR)/test_plugin-test_plugin.Tpo google/protobuf/compiler/$(DEPDIR)/test_plugin-test_plugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/test_plugin.cc' object='google/protobuf/compiler/test_plugin-test_plugin.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zcgzip.o `test -f 'google/protobuf/testing/zcgzip.cc' || echo '$(srcdir)/'`google/protobuf/testing/zcgzip.cc +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/test_plugin-test_plugin.o `test -f 'google/protobuf/compiler/test_plugin.cc' || echo '$(srcdir)/'`google/protobuf/compiler/test_plugin.cc -zcgzip.obj: google/protobuf/testing/zcgzip.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zcgzip.obj -MD -MP -MF $(DEPDIR)/zcgzip.Tpo -c -o zcgzip.obj `if test -f 'google/protobuf/testing/zcgzip.cc'; then $(CYGPATH_W) 'google/protobuf/testing/zcgzip.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/zcgzip.cc'; fi` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/zcgzip.Tpo $(DEPDIR)/zcgzip.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/testing/zcgzip.cc' object='zcgzip.obj' libtool=no @AMDEPBACKSLASH@ +google/protobuf/compiler/test_plugin-test_plugin.obj: google/protobuf/compiler/test_plugin.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT google/protobuf/compiler/test_plugin-test_plugin.obj -MD -MP -MF google/protobuf/compiler/$(DEPDIR)/test_plugin-test_plugin.Tpo -c -o google/protobuf/compiler/test_plugin-test_plugin.obj `if test -f 'google/protobuf/compiler/test_plugin.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/test_plugin.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/test_plugin.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) google/protobuf/compiler/$(DEPDIR)/test_plugin-test_plugin.Tpo google/protobuf/compiler/$(DEPDIR)/test_plugin-test_plugin.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/test_plugin.cc' object='google/protobuf/compiler/test_plugin-test_plugin.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zcgzip.obj `if test -f 'google/protobuf/testing/zcgzip.cc'; then $(CYGPATH_W) 'google/protobuf/testing/zcgzip.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/testing/zcgzip.cc'; fi` +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_plugin_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o google/protobuf/compiler/test_plugin-test_plugin.obj `if test -f 'google/protobuf/compiler/test_plugin.cc'; then $(CYGPATH_W) 'google/protobuf/compiler/test_plugin.cc'; else $(CYGPATH_W) '$(srcdir)/google/protobuf/compiler/test_plugin.cc'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs + -rm -rf google/protobuf/.libs google/protobuf/_libs + -rm -rf google/protobuf/compiler/.libs google/protobuf/compiler/_libs + -rm -rf google/protobuf/compiler/cpp/.libs google/protobuf/compiler/cpp/_libs + -rm -rf google/protobuf/compiler/java/.libs google/protobuf/compiler/java/_libs + -rm -rf google/protobuf/compiler/javamicro/.libs google/protobuf/compiler/javamicro/_libs + -rm -rf google/protobuf/compiler/javanano/.libs google/protobuf/compiler/javanano/_libs + -rm -rf google/protobuf/compiler/python/.libs google/protobuf/compiler/python/_libs + -rm -rf google/protobuf/io/.libs google/protobuf/io/_libs + -rm -rf google/protobuf/stubs/.libs google/protobuf/stubs/_libs install-nobase_dist_protoDATA: $(nobase_dist_proto_DATA) @$(NORMAL_INSTALL) test -z "$(protodir)" || $(MKDIR_P) "$(DESTDIR)$(protodir)" @@ -2950,6 +3487,26 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f google/protobuf/$(DEPDIR)/$(am__dirstamp) + -rm -f google/protobuf/$(am__dirstamp) + -rm -f google/protobuf/compiler/$(DEPDIR)/$(am__dirstamp) + -rm -f google/protobuf/compiler/$(am__dirstamp) + -rm -f google/protobuf/compiler/cpp/$(DEPDIR)/$(am__dirstamp) + -rm -f google/protobuf/compiler/cpp/$(am__dirstamp) + -rm -f google/protobuf/compiler/java/$(DEPDIR)/$(am__dirstamp) + -rm -f google/protobuf/compiler/java/$(am__dirstamp) + -rm -f google/protobuf/compiler/javamicro/$(DEPDIR)/$(am__dirstamp) + -rm -f google/protobuf/compiler/javamicro/$(am__dirstamp) + -rm -f google/protobuf/compiler/javanano/$(DEPDIR)/$(am__dirstamp) + -rm -f google/protobuf/compiler/javanano/$(am__dirstamp) + -rm -f google/protobuf/compiler/python/$(DEPDIR)/$(am__dirstamp) + -rm -f google/protobuf/compiler/python/$(am__dirstamp) + -rm -f google/protobuf/io/$(DEPDIR)/$(am__dirstamp) + -rm -f google/protobuf/io/$(am__dirstamp) + -rm -f google/protobuf/stubs/$(DEPDIR)/$(am__dirstamp) + -rm -f google/protobuf/stubs/$(am__dirstamp) + -rm -f google/protobuf/testing/$(DEPDIR)/$(am__dirstamp) + -rm -f google/protobuf/testing/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -2962,7 +3519,7 @@ clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libtool clean-local mostlyclean-am distclean: distclean-am - -rm -rf ./$(DEPDIR) + -rm -rf google/protobuf/$(DEPDIR) google/protobuf/compiler/$(DEPDIR) google/protobuf/compiler/cpp/$(DEPDIR) google/protobuf/compiler/java/$(DEPDIR) google/protobuf/compiler/javamicro/$(DEPDIR) google/protobuf/compiler/javanano/$(DEPDIR) google/protobuf/compiler/python/$(DEPDIR) google/protobuf/io/$(DEPDIR) google/protobuf/stubs/$(DEPDIR) google/protobuf/testing/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -3009,7 +3566,7 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) + -rm -rf google/protobuf/$(DEPDIR) google/protobuf/compiler/$(DEPDIR) google/protobuf/compiler/cpp/$(DEPDIR) google/protobuf/compiler/java/$(DEPDIR) google/protobuf/compiler/javamicro/$(DEPDIR) google/protobuf/compiler/javanano/$(DEPDIR) google/protobuf/compiler/python/$(DEPDIR) google/protobuf/io/$(DEPDIR) google/protobuf/stubs/$(DEPDIR) google/protobuf/testing/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/src/google/protobuf/SEBS b/src/google/protobuf/SEBS new file mode 100644 index 0000000..ba33c73 --- /dev/null +++ b/src/google/protobuf/SEBS @@ -0,0 +1,240 @@ +# **EXPERIMENTAL** +# +# See http://sebs.googlecode.com +# +# This is an experimental build definition file using the SEBS build system. +# I (Kenton Varda, maintainer of Protocol Buffers) happen to be the author of +# SEBS, though SEBS is not a Google project. I'm sticking this file in +# protobuf's SVN because that's the easiest place for me to put it, and it +# shouldn't harm anyone. This file is not included in the distribution. +# +# Currently, to use this file, you must generate config.h and put it at the +# top level of the source tree. + +_cpp = sebs.import_("//sebs/cpp.sebs") + +# ==================================================================== +# Public targets + +protobuf_lite = _cpp.Library( + name = "protobuf-lite", + srcs = [ "stubs/common.cc", + "stubs/once.cc", + "stubs/hash.cc", + "stubs/hash.h", + "stubs/map-util.h", + "stubs/stl_util-inl.h", + "extension_set.cc", + "generated_message_util.cc", + "message_lite.cc", + "repeated_field.cc", + "wire_format_lite.cc", + "io/coded_stream.cc", + "io/zero_copy_stream.cc", + "io/zero_copy_stream_impl_lite.cc" ], + deps = [ _cpp.SystemLibrary(name = "pthread") ]) + +protobuf = _cpp.Library( + name = "protobuf", + srcs = [ "stubs/strutil.cc", + "stubs/strutil.h", + "stubs/substitute.cc", + "stubs/substitute.h", + "stubs/structurally_valid.cc", + "descriptor.cc", + "descriptor.pb.cc", + "descriptor_database.cc", + "dynamic_message.cc", + "extension_set_heavy.cc", + "generated_message_reflection.cc", + "message.cc", + "reflection_ops.cc", + "service.cc", + "text_format.cc", + "unknown_field_set.cc", + "wire_format.cc", + "io/gzip_stream.cc", + "io/printer.cc", + "io/tokenizer.cc", + "io/zero_copy_stream_impl.cc", + "compiler/importer.cc", + "compiler/parser.cc" ], + deps = [ protobuf_lite, + _cpp.SystemLibrary(name = "z") ]) + +libprotoc = _cpp.Library( + name = "protoc", + srcs = [ "compiler/code_generator.cc", + "compiler/command_line_interface.cc", + "compiler/cpp/cpp_enum.cc", + "compiler/cpp/cpp_enum.h", + "compiler/cpp/cpp_enum_field.cc", + "compiler/cpp/cpp_enum_field.h", + "compiler/cpp/cpp_extension.cc", + "compiler/cpp/cpp_extension.h", + "compiler/cpp/cpp_field.cc", + "compiler/cpp/cpp_field.h", + "compiler/cpp/cpp_file.cc", + "compiler/cpp/cpp_file.h", + "compiler/cpp/cpp_generator.cc", + "compiler/cpp/cpp_helpers.cc", + "compiler/cpp/cpp_helpers.h", + "compiler/cpp/cpp_message.cc", + "compiler/cpp/cpp_message.h", + "compiler/cpp/cpp_message_field.cc", + "compiler/cpp/cpp_message_field.h", + "compiler/cpp/cpp_primitive_field.cc", + "compiler/cpp/cpp_primitive_field.h", + "compiler/cpp/cpp_service.cc", + "compiler/cpp/cpp_service.h", + "compiler/cpp/cpp_string_field.cc", + "compiler/cpp/cpp_string_field.h", + "compiler/java/java_enum.cc", + "compiler/java/java_enum.h", + "compiler/java/java_enum_field.cc", + "compiler/java/java_enum_field.h", + "compiler/java/java_extension.cc", + "compiler/java/java_extension.h", + "compiler/java/java_field.cc", + "compiler/java/java_field.h", + "compiler/java/java_file.cc", + "compiler/java/java_file.h", + "compiler/java/java_generator.cc", + "compiler/java/java_helpers.cc", + "compiler/java/java_helpers.h", + "compiler/java/java_message.cc", + "compiler/java/java_message.h", + "compiler/java/java_message_field.cc", + "compiler/java/java_message_field.h", + "compiler/java/java_primitive_field.cc", + "compiler/java/java_primitive_field.h", + "compiler/java/java_service.cc", + "compiler/java/java_service.h", + "compiler/python/python_generator.cc" ], + deps = [ protobuf ]) + +protoc = _cpp.Binary( + name = "protoc", + srcs = [ "compiler/main.cc" ], + deps = [ libprotoc ]) + +# ==================================================================== +# ProtobufLibrary rule class + +class ProtobufLibrary(sebs.Rule): + argument_spec = sebs.ArgumentSpec(srcs = [sebs.Artifact], + deps = ([sebs.Rule], []), + lite = (bool, False)) + + def _expand(self, args): + for dep in args.deps: + if not isinstance(dep, ProtobufLibrary): + raise sebs.DefinitionError( + "Dependency of ProtobufLibrary is not a ProtobufLibrary: %s" % dep) + + protoc.expand_once() + + # We must build protoc for the host configuration to allow cross-compiling. + host_protoc = self.context.configured_artifact(protoc.binary, "host") + + protoc_action = self.context.action(self, "protobuf") + protoc_args = [host_protoc, "-Isrc", "-Itmp", "-Iinclude","--cpp_out=tmp"] + + cpp_srcs = [] + for src in args.srcs: + protoc_args.append(src) + + # We cannot build .proto files from other packages because the .pb.cc + # and .pb.h files would be written to that package, and we aren't allowed + # to write to other packages. + if self.context.local_filename(src) is None: + raise sebs.DefinitionError( + "Source file is not in this package: %s" % src) + + cc_artifact = self.context.derived_artifact(src, ".pb.cc", protoc_action) + header_artifact = self.context.derived_artifact( + src, ".pb.h", protoc_action) + + cpp_srcs.append(cc_artifact) + cpp_srcs.append(header_artifact) + + protoc_action.set_command( + sebs.SubprocessCommand(protoc_action, protoc_args, implicit = cpp_srcs)) + + deps = list(args.deps) + if args.lite: + deps.append(protobuf_lite) + else: + deps.append(protobuf) + + self.__cpp_library = _cpp.Library(srcs = cpp_srcs, deps = deps, + context = self.context) + self.__cpp_library.label = self.label + self.outputs = [] + + def as_cpp_library(self): + self.expand_once() + return self.__cpp_library + +# ==================================================================== +# Tests + +_lite_test_protos = ProtobufLibrary( + srcs = [ "unittest_lite.proto", + "unittest_import_lite.proto" ], + lite = True) +_test_protos = ProtobufLibrary( + srcs = [ "unittest.proto", + "unittest_empty.proto", + "unittest_import.proto", + "unittest_mset.proto", + "unittest_optimize_for.proto", + "unittest_embed_optimize_for.proto", + "unittest_custom_options.proto", + "unittest_lite_imports_nonlite.proto", + "compiler/cpp/cpp_test_bad_identifiers.proto" ], + deps = [ _lite_test_protos ]) + +_test_util = _cpp.Library( + name = "test_util", + srcs = [ "test_util.cc", + "test_util.h", + "testing/googletest.cc", + "testing/googletest.h", + "testing/file.cc", + "testing/file.h" ], + deps = [ protobuf, _test_protos, _cpp.SystemLibrary(name = "gtest")] ) + +protobuf_lite_test = _cpp.Test( + srcs = [ "lite_unittest.cc", + "test_util_lite.cc", + "test_util_lite.h" ], + deps = [ _lite_test_protos ]) + +protobuf_test = _cpp.Test( + srcs = [ "stubs/common_unittest.cc", + "stubs/once_unittest.cc", + "stubs/strutil_unittest.cc", + "stubs/structurally_valid_unittest.cc", + "descriptor_database_unittest.cc", + "descriptor_unittest.cc", + "dynamic_message_unittest.cc", + "extension_set_unittest.cc", + "generated_message_reflection_unittest.cc", + "message_unittest.cc", + "reflection_ops_unittest.cc", + "repeated_field_unittest.cc", + "text_format_unittest.cc", + "unknown_field_set_unittest.cc", + "wire_format_unittest.cc", + "io/coded_stream_unittest.cc", + "io/printer_unittest.cc", + "io/tokenizer_unittest.cc", + "io/zero_copy_stream_unittest.cc", + "compiler/command_line_interface_unittest.cc", + "compiler/importer_unittest.cc", + "compiler/parser_unittest.cc", + "compiler/cpp/cpp_bootstrap_unittest.cc", + "compiler/cpp/cpp_unittest.cc" ], + deps = [ protobuf, libprotoc, _test_util, + _cpp.SystemLibrary(name = "gtest_main") ]) diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc index 3413a36..bc4800a 100644 --- a/src/google/protobuf/compiler/code_generator.cc +++ b/src/google/protobuf/compiler/code_generator.cc @@ -42,19 +42,28 @@ namespace protobuf { namespace compiler { CodeGenerator::~CodeGenerator() {} -OutputDirectory::~OutputDirectory() {} +GeneratorContext::~GeneratorContext() {} -io::ZeroCopyOutputStream* OutputDirectory::OpenForInsert( +io::ZeroCopyOutputStream* +GeneratorContext::OpenForAppend(const string& filename) { + return NULL; +} + +io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert( const string& filename, const string& insertion_point) { - GOOGLE_LOG(FATAL) << "This OutputDirectory does not support insertion."; + GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion."; return NULL; // make compiler happy } +void GeneratorContext::ListParsedFiles( + vector* output) { + GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles"; +} + // Parses a set of comma-delimited name/value pairs. void ParseGeneratorParameter(const string& text, vector >* output) { - vector parts; - SplitStringUsing(text, ",", &parts); + vector parts = Split(text, ",", true); for (int i = 0; i < parts.size(); i++) { string::size_type equals_pos = parts[i].find_first_of('='); diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index ea094cd..541f784 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -53,7 +53,7 @@ namespace compiler { // Defined in this file. class CodeGenerator; -class OutputDirectory; +class GeneratorContext; // The abstract interface to a class which generates code implementing a // particular proto file in a particular language. A number of these may @@ -76,7 +76,7 @@ class LIBPROTOC_EXPORT CodeGenerator { // the problem (e.g. "invalid parameter") and returns false. virtual bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* generator_context, string* error) const = 0; private: @@ -85,11 +85,12 @@ class LIBPROTOC_EXPORT CodeGenerator { // CodeGenerators generate one or more files in a given directory. This // abstract interface represents the directory to which the CodeGenerator is -// to write. -class LIBPROTOC_EXPORT OutputDirectory { +// to write and other information about the context in which the Generator +// runs. +class LIBPROTOC_EXPORT GeneratorContext { public: - inline OutputDirectory() {} - virtual ~OutputDirectory(); + inline GeneratorContext() {} + virtual ~GeneratorContext(); // Opens the given file, truncating it if it exists, and returns a // ZeroCopyOutputStream that writes to the file. The caller takes ownership @@ -103,6 +104,9 @@ class LIBPROTOC_EXPORT OutputDirectory { // contain "." or ".." components. virtual io::ZeroCopyOutputStream* Open(const string& filename) = 0; + // Similar to Open() but the output will be appended to the file if exists + virtual io::ZeroCopyOutputStream* OpenForAppend(const string& filename); + // Creates a ZeroCopyOutputStream which will insert code into the given file // at the given insertion point. See plugin.proto (plugin.pb.h) for more // information on insertion points. The default implementation @@ -112,10 +116,19 @@ class LIBPROTOC_EXPORT OutputDirectory { virtual io::ZeroCopyOutputStream* OpenForInsert( const string& filename, const string& insertion_point); + // Returns a vector of FileDescriptors for all the files being compiled + // in this run. Useful for languages, such as Go, that treat files + // differently when compiled as a set rather than individually. + virtual void ListParsedFiles(vector* output); + private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext); }; +// The type GeneratorContext was once called OutputDirectory. This typedef +// provides backward compatibility. +typedef GeneratorContext OutputDirectory; + // Several code generators treat the parameter argument as holding a // list of options separated by commas. This helper function parses // a set of comma-delimited name/value pairs: e.g., diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index d3495ca..1acc8fb 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -48,6 +48,11 @@ #include #include +#include +#include + +#include +#include #include #include #include @@ -56,14 +61,13 @@ #include #include #include +#include #include #include -#include #include #include -#include -#include -#include +#include +#include namespace google { @@ -144,7 +148,7 @@ void AddTrailingSlash(string* path) { bool VerifyDirectoryExists(const string& path) { if (path.empty()) return true; - if (access(path.c_str(), W_OK) == -1) { + if (access(path.c_str(), F_OK) == -1) { cerr << path << ": " << strerror(errno) << endl; return false; } else { @@ -158,8 +162,7 @@ bool VerifyDirectoryExists(const string& path) { // directories listed in |filename|. bool TryCreateParentDirectory(const string& prefix, const string& filename) { // Recursively create parent directories to the output file. - vector parts; - SplitStringUsing(filename, "/", &parts); + vector parts = Split(filename, "/", true); string path_so_far = prefix; for (int i = 0; i < parts.size() - 1; i++) { path_so_far += parts[i]; @@ -182,14 +185,23 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) { class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, public io::ErrorCollector { public: - ErrorPrinter(ErrorFormat format) : format_(format) {} + ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL) + : format_(format), tree_(tree) {} ~ErrorPrinter() {} // implements MultiFileErrorCollector ------------------------------ void AddError(const string& filename, int line, int column, const string& message) { - cerr << filename; + // Print full path when running under MSVS + string dfile; + if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && + tree_ != NULL && + tree_->VirtualFileToDiskFile(filename, &dfile)) { + cerr << dfile; + } else { + cerr << filename; + } // Users typically expect 1-based line/column numbers, so we add 1 // to each here. @@ -215,16 +227,17 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, private: const ErrorFormat format_; + DiskSourceTree *tree_; }; // ------------------------------------------------------------------- -// An OutputDirectory implementation that buffers files in memory, then dumps +// A GeneratorContext implementation that buffers files in memory, then dumps // them all to disk on demand. -class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory { +class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { public: - MemoryOutputDirectory(); - ~MemoryOutputDirectory(); + GeneratorContextImpl(const vector& parsed_files); + ~GeneratorContextImpl(); // Write all files in the directory to disk at the given output location, // which must end in a '/'. @@ -238,10 +251,14 @@ class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory { // format, unless one has already been written. void AddJarManifest(); - // implements OutputDirectory -------------------------------------- + // implements GeneratorContext -------------------------------------- io::ZeroCopyOutputStream* Open(const string& filename); + io::ZeroCopyOutputStream* OpenForAppend(const string& filename); io::ZeroCopyOutputStream* OpenForInsert( const string& filename, const string& insertion_point); + void ListParsedFiles(vector* output) { + *output = parsed_files_; + } private: friend class MemoryOutputStream; @@ -249,14 +266,16 @@ class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory { // map instead of hash_map so that files are written in order (good when // writing zips). map files_; + const vector& parsed_files_; bool had_error_; }; class CommandLineInterface::MemoryOutputStream : public io::ZeroCopyOutputStream { public: - MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename); - MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename, + MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, + bool append_mode); + MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, const string& insertion_point); virtual ~MemoryOutputStream(); @@ -267,27 +286,33 @@ class CommandLineInterface::MemoryOutputStream private: // Where to insert the string when it's done. - MemoryOutputDirectory* directory_; + GeneratorContextImpl* directory_; string filename_; string insertion_point_; // The string we're building. string data_; + // Whether we should append the output stream to the existing file. + bool append_mode_; + // StringOutputStream writing to data_. scoped_ptr inner_; }; // ------------------------------------------------------------------- -CommandLineInterface::MemoryOutputDirectory::MemoryOutputDirectory() - : had_error_(false) {} +CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl( + const vector& parsed_files) + : parsed_files_(parsed_files), + had_error_(false) { +} -CommandLineInterface::MemoryOutputDirectory::~MemoryOutputDirectory() { +CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() { STLDeleteValues(&files_); } -bool CommandLineInterface::MemoryOutputDirectory::WriteAllToDisk( +bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( const string& prefix) { if (had_error_) { return false; @@ -362,7 +387,7 @@ bool CommandLineInterface::MemoryOutputDirectory::WriteAllToDisk( return true; } -bool CommandLineInterface::MemoryOutputDirectory::WriteAllToZip( +bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( const string& filename) { if (had_error_) { return false; @@ -403,7 +428,7 @@ bool CommandLineInterface::MemoryOutputDirectory::WriteAllToZip( return true; } -void CommandLineInterface::MemoryOutputDirectory::AddJarManifest() { +void CommandLineInterface::GeneratorContextImpl::AddJarManifest() { string** map_slot = &files_["META-INF/MANIFEST.MF"]; if (*map_slot == NULL) { *map_slot = new string( @@ -413,13 +438,19 @@ void CommandLineInterface::MemoryOutputDirectory::AddJarManifest() { } } -io::ZeroCopyOutputStream* CommandLineInterface::MemoryOutputDirectory::Open( +io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open( const string& filename) { - return new MemoryOutputStream(this, filename); + return new MemoryOutputStream(this, filename, false); } io::ZeroCopyOutputStream* -CommandLineInterface::MemoryOutputDirectory::OpenForInsert( +CommandLineInterface::GeneratorContextImpl::OpenForAppend( + const string& filename) { + return new MemoryOutputStream(this, filename, true); +} + +io::ZeroCopyOutputStream* +CommandLineInterface::GeneratorContextImpl::OpenForInsert( const string& filename, const string& insertion_point) { return new MemoryOutputStream(this, filename, insertion_point); } @@ -427,14 +458,15 @@ CommandLineInterface::MemoryOutputDirectory::OpenForInsert( // ------------------------------------------------------------------- CommandLineInterface::MemoryOutputStream::MemoryOutputStream( - MemoryOutputDirectory* directory, const string& filename) + GeneratorContextImpl* directory, const string& filename, bool append_mode) : directory_(directory), filename_(filename), + append_mode_(append_mode), inner_(new io::StringOutputStream(&data_)) { } CommandLineInterface::MemoryOutputStream::MemoryOutputStream( - MemoryOutputDirectory* directory, const string& filename, + GeneratorContextImpl* directory, const string& filename, const string& insertion_point) : directory_(directory), filename_(filename), @@ -452,8 +484,12 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { if (insertion_point_.empty()) { // This was just a regular Open(). if (*map_slot != NULL) { - cerr << filename_ << ": Tried to write the same file twice." << endl; - directory_->had_error_ = true; + if (append_mode_) { + (*map_slot)->append(data_); + } else { + cerr << filename_ << ": Tried to write the same file twice." << endl; + directory_->had_error_ = true; + } return; } @@ -546,8 +582,10 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { CommandLineInterface::CommandLineInterface() : mode_(MODE_COMPILE), + print_mode_(PRINT_NONE), error_format_(ERROR_FORMAT_GCC), imports_in_descriptor_set_(false), + source_info_in_descriptor_set_(false), disallow_services_(false), inputs_are_proto_path_relative_(false) {} CommandLineInterface::~CommandLineInterface() {} @@ -556,9 +594,23 @@ void CommandLineInterface::RegisterGenerator(const string& flag_name, CodeGenerator* generator, const string& help_text) { GeneratorInfo info; + info.flag_name = flag_name; + info.generator = generator; + info.help_text = help_text; + generators_by_flag_name_[flag_name] = info; +} + +void CommandLineInterface::RegisterGenerator(const string& flag_name, + const string& option_flag_name, + CodeGenerator* generator, + const string& help_text) { + GeneratorInfo info; + info.flag_name = flag_name; + info.option_flag_name = option_flag_name; info.generator = generator; info.help_text = help_text; - generators_[flag_name] = info; + generators_by_flag_name_[flag_name] = info; + generators_by_option_name_[option_flag_name] = info; } void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) { @@ -567,7 +619,14 @@ void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) { int CommandLineInterface::Run(int argc, const char* const argv[]) { Clear(); - if (!ParseArguments(argc, argv)) return 1; + switch (ParseArguments(argc, argv)) { + case PARSE_ARGUMENT_DONE_AND_EXIT: + return 0; + case PARSE_ARGUMENT_FAIL: + return 1; + case PARSE_ARGUMENT_DONE_AND_CONTINUE: + break; + } // Set up the source tree. DiskSourceTree source_tree; @@ -583,7 +642,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } // Allocate the Importer. - ErrorPrinter error_collector(error_format_); + ErrorPrinter error_collector(error_format_, &source_tree); Importer importer(&source_tree, &error_collector); vector parsed_files; @@ -591,7 +650,9 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { // Parse each file. for (int i = 0; i < input_files_.size(); i++) { // Import the file. + importer.AddUnusedImportTrackFile(input_files_[i]); const FileDescriptor* parsed_file = importer.Import(input_files_[i]); + importer.ClearUnusedImportTrackFiles(); if (parsed_file == NULL) return 1; parsed_files.push_back(parsed_file); @@ -603,11 +664,11 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } - // We construct a separate OutputDirectory for each output location. Note + // We construct a separate GeneratorContext for each output location. Note // that two code generators may output to the same location, in which case - // they should share a single OutputDirectory (so that OpenForInsert() works). - typedef hash_map OutputDirectoryMap; - OutputDirectoryMap output_directories; + // they should share a single GeneratorContext so that OpenForInsert() works. + typedef hash_map GeneratorContextMap; + GeneratorContextMap output_directories; // Generate output. if (mode_ == MODE_COMPILE) { @@ -617,11 +678,11 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { !HasSuffixString(output_location, ".jar")) { AddTrailingSlash(&output_location); } - MemoryOutputDirectory** map_slot = &output_directories[output_location]; + GeneratorContextImpl** map_slot = &output_directories[output_location]; if (*map_slot == NULL) { // First time we've seen this output location. - *map_slot = new MemoryOutputDirectory; + *map_slot = new GeneratorContextImpl(parsed_files); } if (!GenerateOutput(parsed_files, output_directives_[i], *map_slot)) { @@ -632,10 +693,10 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } // Write all output to disk. - for (OutputDirectoryMap::iterator iter = output_directories.begin(); + for (GeneratorContextMap::iterator iter = output_directories.begin(); iter != output_directories.end(); ++iter) { const string& location = iter->first; - MemoryOutputDirectory* directory = iter->second; + GeneratorContextImpl* directory = iter->second; if (HasSuffixString(location, "/")) { if (!directory->WriteAllToDisk(location)) { STLDeleteValues(&output_directories); @@ -680,6 +741,25 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } + if (mode_ == MODE_PRINT) { + switch (print_mode_) { + case PRINT_FREE_FIELDS: + for (int i = 0; i < parsed_files.size(); ++i) { + const FileDescriptor* fd = parsed_files[i]; + for (int j = 0; j < fd->message_type_count(); ++j) { + PrintFreeFieldNumbers(fd->message_type(j)); + } + } + break; + case PRINT_NONE: + GOOGLE_LOG(ERROR) << "If the code reaches here, it usually means a bug of " + "flag parsing in the CommonadLineInterface."; + return 1; + + // Do not add a default case. + } + } + return 0; } @@ -694,7 +774,9 @@ void CommandLineInterface::Clear() { descriptor_set_name_.clear(); mode_ = MODE_COMPILE; + print_mode_ = PRINT_NONE; imports_in_descriptor_set_ = false; + source_info_in_descriptor_set_ = false; disallow_services_ = false; } @@ -737,7 +819,8 @@ bool CommandLineInterface::MakeInputsBeProtoPathRelative( return true; } -bool CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { +CommandLineInterface::ParseArgumentStatus +CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { executable_name_ = argv[0]; // Iterate through all arguments and parse them. @@ -751,41 +834,50 @@ bool CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { if (name == "--decode") { cerr << "To decode an unknown message, use --decode_raw." << endl; } - return false; + return PARSE_ARGUMENT_FAIL; } else { ++i; value = argv[i]; } } - if (!InterpretArgument(name, value)) return false; + ParseArgumentStatus status = InterpretArgument(name, value); + if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE) + return status; } // If no --proto_path was given, use the current working directory. if (proto_path_.empty()) { - proto_path_.push_back(make_pair("", ".")); + // Don't use make_pair as the old/default standard library on Solaris + // doesn't support it without explicit template parameters, which are + // incompatible with C++0x's make_pair. + proto_path_.push_back(pair("", ".")); } // Check some errror cases. bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty(); if (decoding_raw && !input_files_.empty()) { cerr << "When using --decode_raw, no input files should be given." << endl; - return false; + return PARSE_ARGUMENT_FAIL; } else if (!decoding_raw && input_files_.empty()) { cerr << "Missing input file." << endl; - return false; + return PARSE_ARGUMENT_FAIL; } if (mode_ == MODE_COMPILE && output_directives_.empty() && descriptor_set_name_.empty()) { cerr << "Missing output directives." << endl; - return false; + return PARSE_ARGUMENT_FAIL; } if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) { cerr << "--include_imports only makes sense when combined with " "--descriptor_set_out." << endl; } + if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) { + cerr << "--include_source_info only makes sense when combined with " + "--descriptor_set_out." << endl; + } - return true; + return PARSE_ARGUMENT_DONE_AND_CONTINUE; } bool CommandLineInterface::ParseArgument(const char* arg, @@ -835,8 +927,10 @@ bool CommandLineInterface::ParseArgument(const char* arg, if (*name == "-h" || *name == "--help" || *name == "--disallow_services" || *name == "--include_imports" || + *name == "--include_source_info" || *name == "--version" || - *name == "--decode_raw") { + *name == "--decode_raw" || + *name == "--print_free_field_numbers") { // HACK: These are the only flags that don't take a value. // They probably should not be hard-coded like this but for now it's // not worth doing better. @@ -847,8 +941,9 @@ bool CommandLineInterface::ParseArgument(const char* arg, return true; } -bool CommandLineInterface::InterpretArgument(const string& name, - const string& value) { +CommandLineInterface::ParseArgumentStatus +CommandLineInterface::InterpretArgument(const string& name, + const string& value) { if (name.empty()) { // Not a flag. Just a filename. if (value.empty()) { @@ -856,7 +951,7 @@ bool CommandLineInterface::InterpretArgument(const string& name, "arguments to " << executable_name_ << ". This is actually " "sort of hard to do. Congrats. Unfortunately it is not valid " "input so the program is going to die now." << endl; - return false; + return PARSE_ARGUMENT_FAIL; } input_files_.push_back(value); @@ -865,14 +960,14 @@ bool CommandLineInterface::InterpretArgument(const string& name, // Java's -classpath (and some other languages) delimits path components // with colons. Let's accept that syntax too just to make things more // intuitive. - vector parts; - SplitStringUsing(value, kPathSeparator, &parts); + vector parts = Split( + value, kPathSeparator, true); for (int i = 0; i < parts.size(); i++) { string virtual_path; string disk_path; - int equals_pos = parts[i].find_first_of('='); + string::size_type equals_pos = parts[i].find_first_of('='); if (equals_pos == string::npos) { virtual_path = ""; disk_path = parts[i]; @@ -884,7 +979,7 @@ bool CommandLineInterface::InterpretArgument(const string& name, if (disk_path.empty()) { cerr << "--proto_path passed empty directory name. (Use \".\" for " "current directory.)" << endl; - return false; + return PARSE_ARGUMENT_FAIL; } // Make sure disk path exists, warn otherwise. @@ -892,35 +987,45 @@ bool CommandLineInterface::InterpretArgument(const string& name, cerr << disk_path << ": warning: directory does not exist." << endl; } - proto_path_.push_back(make_pair(virtual_path, disk_path)); + // Don't use make_pair as the old/default standard library on Solaris + // doesn't support it without explicit template parameters, which are + // incompatible with C++0x's make_pair. + proto_path_.push_back(pair(virtual_path, disk_path)); } } else if (name == "-o" || name == "--descriptor_set_out") { if (!descriptor_set_name_.empty()) { cerr << name << " may only be passed once." << endl; - return false; + return PARSE_ARGUMENT_FAIL; } if (value.empty()) { cerr << name << " requires a non-empty value." << endl; - return false; + return PARSE_ARGUMENT_FAIL; } if (mode_ != MODE_COMPILE) { cerr << "Cannot use --encode or --decode and generate descriptors at the " "same time." << endl; - return false; + return PARSE_ARGUMENT_FAIL; } descriptor_set_name_ = value; } else if (name == "--include_imports") { if (imports_in_descriptor_set_) { cerr << name << " may only be passed once." << endl; - return false; + return PARSE_ARGUMENT_FAIL; } imports_in_descriptor_set_ = true; + } else if (name == "--include_source_info") { + if (source_info_in_descriptor_set_) { + cerr << name << " may only be passed once." << endl; + return PARSE_ARGUMENT_FAIL; + } + source_info_in_descriptor_set_ = true; + } else if (name == "-h" || name == "--help") { PrintHelpText(); - return false; // Exit without running compiler. + return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. } else if (name == "--version") { if (!version_info_.empty()) { @@ -929,7 +1034,7 @@ bool CommandLineInterface::InterpretArgument(const string& name, cout << "libprotoc " << protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION) << endl; - return false; // Exit without running compiler. + return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. } else if (name == "--disallow_services") { disallow_services_ = true; @@ -938,12 +1043,12 @@ bool CommandLineInterface::InterpretArgument(const string& name, name == "--decode_raw") { if (mode_ != MODE_COMPILE) { cerr << "Only one of --encode and --decode can be specified." << endl; - return false; + return PARSE_ARGUMENT_FAIL; } if (!output_directives_.empty() || !descriptor_set_name_.empty()) { cerr << "Cannot use " << name << " and generate code or descriptors at the same time." << endl; - return false; + return PARSE_ARGUMENT_FAIL; } mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE; @@ -953,10 +1058,10 @@ bool CommandLineInterface::InterpretArgument(const string& name, if (name == "--decode") { cerr << "To decode an unknown message, use --decode_raw." << endl; } - return false; + return PARSE_ARGUMENT_FAIL; } else if (!value.empty() && name == "--decode_raw") { cerr << "--decode_raw does not take a parameter." << endl; - return false; + return PARSE_ARGUMENT_FAIL; } codec_type_ = value; @@ -968,16 +1073,16 @@ bool CommandLineInterface::InterpretArgument(const string& name, error_format_ = ERROR_FORMAT_MSVS; } else { cerr << "Unknown error format: " << value << endl; - return false; + return PARSE_ARGUMENT_FAIL; } } else if (name == "--plugin") { if (plugin_prefix_.empty()) { cerr << "This compiler does not support plugins." << endl; - return false; + return PARSE_ARGUMENT_FAIL; } - string name; + string plugin_name; string path; string::size_type equals_pos = value.find_first_of('='); @@ -985,57 +1090,81 @@ bool CommandLineInterface::InterpretArgument(const string& name, // Use the basename of the file. string::size_type slash_pos = value.find_last_of('/'); if (slash_pos == string::npos) { - name = value; + plugin_name = value; } else { - name = value.substr(slash_pos + 1); + plugin_name = value.substr(slash_pos + 1); } path = value; } else { - name = value.substr(0, equals_pos); + plugin_name = value.substr(0, equals_pos); path = value.substr(equals_pos + 1); } - plugins_[name] = path; + plugins_[plugin_name] = path; + } else if (name == "--print_free_field_numbers") { + if (mode_ != MODE_COMPILE) { + cerr << "Cannot use " << name << " and use --encode, --decode or print " + << "other info at the same time." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (!output_directives_.empty() || !descriptor_set_name_.empty()) { + cerr << "Cannot use " << name + << " and generate code or descriptors at the same time." << endl; + return PARSE_ARGUMENT_FAIL; + } + mode_ = MODE_PRINT; + print_mode_ = PRINT_FREE_FIELDS; } else { // Some other flag. Look it up in the generators list. - const GeneratorInfo* generator_info = FindOrNull(generators_, name); + const GeneratorInfo* generator_info = + FindOrNull(generators_by_flag_name_, name); if (generator_info == NULL && (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) { - cerr << "Unknown flag: " << name << endl; - return false; - } + // Check if it's a generator option flag. + generator_info = FindOrNull(generators_by_option_name_, name); + if (generator_info == NULL) { + cerr << "Unknown flag: " << name << endl; + return PARSE_ARGUMENT_FAIL; + } else { + string* parameters = &generator_parameters_[generator_info->flag_name]; + if (!parameters->empty()) { + parameters->append(","); + } + parameters->append(value); + } + } else { + // It's an output flag. Add it to the output directives. + if (mode_ != MODE_COMPILE) { + cerr << "Cannot use --encode, --decode or print .proto info and " + "generate code at the same time." << endl; + return PARSE_ARGUMENT_FAIL; + } - // It's an output flag. Add it to the output directives. - if (mode_ != MODE_COMPILE) { - cerr << "Cannot use --encode or --decode and generate code at the " - "same time." << endl; - return false; - } + OutputDirective directive; + directive.name = name; + if (generator_info == NULL) { + directive.generator = NULL; + } else { + directive.generator = generator_info->generator; + } - OutputDirective directive; - directive.name = name; - if (generator_info == NULL) { - directive.generator = NULL; - } else { - directive.generator = generator_info->generator; - } + // Split value at ':' to separate the generator parameter from the + // filename. However, avoid doing this if the colon is part of a valid + // Windows-style absolute path. + string::size_type colon_pos = value.find_first_of(':'); + if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) { + directive.output_location = value; + } else { + directive.parameter = value.substr(0, colon_pos); + directive.output_location = value.substr(colon_pos + 1); + } - // Split value at ':' to separate the generator parameter from the - // filename. However, avoid doing this if the colon is part of a valid - // Windows-style absolute path. - string::size_type colon_pos = value.find_first_of(':'); - if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) { - directive.output_location = value; - } else { - directive.parameter = value.substr(0, colon_pos); - directive.output_location = value.substr(colon_pos + 1); + output_directives_.push_back(directive); } - - output_directives_.push_back(directive); } - return true; + return PARSE_ARGUMENT_DONE_AND_CONTINUE; } void CommandLineInterface::PrintHelpText() { @@ -1068,9 +1197,20 @@ void CommandLineInterface::PrintHelpText() { " --include_imports When using --descriptor_set_out, also include\n" " all dependencies of the input files in the\n" " set, so that the set is self-contained.\n" +" --include_source_info When using --descriptor_set_out, do not strip\n" +" SourceCodeInfo from the FileDescriptorProto.\n" +" This results in vastly larger descriptors that\n" +" include information about the original\n" +" location of each decl in the source file as\n" +" well as surrounding comments.\n" " --error_format=FORMAT Set the format in which to print errors.\n" " FORMAT may be 'gcc' (the default) or 'msvs'\n" -" (Microsoft Visual Studio format)." << endl; +" (Microsoft Visual Studio format).\n" +" --print_free_field_numbers Print the free field numbers of the messages\n" +" defined in the given proto files. Groups share\n" +" the same field number space with the parent \n" +" message. Extension ranges are counted as \n" +" occupied fields numbers." << endl; if (!plugin_prefix_.empty()) { cerr << " --plugin=EXECUTABLE Specifies a plugin executable to use.\n" @@ -1083,8 +1223,8 @@ void CommandLineInterface::PrintHelpText() { " the executable's own name differs." << endl; } - for (GeneratorMap::iterator iter = generators_.begin(); - iter != generators_.end(); ++iter) { + for (GeneratorMap::iterator iter = generators_by_flag_name_.begin(); + iter != generators_by_flag_name_.end(); ++iter) { // FIXME(kenton): If the text is long enough it will wrap, which is ugly, // but fixing this nicely (e.g. splitting on spaces) is probably more // trouble than it's worth. @@ -1097,7 +1237,7 @@ void CommandLineInterface::PrintHelpText() { bool CommandLineInterface::GenerateOutput( const vector& parsed_files, const OutputDirective& output_directive, - OutputDirectory* output_directory) { + GeneratorContext* generator_context) { // Call the generator. string error; if (output_directive.generator == NULL) { @@ -1112,16 +1252,22 @@ bool CommandLineInterface::GenerateOutput( if (!GeneratePluginOutput(parsed_files, plugin_name, output_directive.parameter, - output_directory, &error)) { + generator_context, &error)) { cerr << output_directive.name << ": " << error << endl; return false; } } else { // Regular generator. + string parameters = output_directive.parameter; + if (!generator_parameters_[output_directive.name].empty()) { + if (!parameters.empty()) { + parameters.append(","); + } + parameters.append(generator_parameters_[output_directive.name]); + } for (int i = 0; i < parsed_files.size(); i++) { - if (!output_directive.generator->Generate( - parsed_files[i], output_directive.parameter, - output_directory, &error)) { + if (!output_directive.generator->Generate(parsed_files[i], parameters, + generator_context, &error)) { // Generator returned an error. cerr << output_directive.name << ": " << parsed_files[i]->name() << ": " << error << endl; @@ -1137,7 +1283,7 @@ bool CommandLineInterface::GeneratePluginOutput( const vector& parsed_files, const string& plugin_name, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* generator_context, string* error) { CodeGeneratorRequest request; CodeGeneratorResponse response; @@ -1150,8 +1296,9 @@ bool CommandLineInterface::GeneratePluginOutput( set already_seen; for (int i = 0; i < parsed_files.size(); i++) { request.add_file_to_generate(parsed_files[i]->name()); - GetTransitiveDependencies(parsed_files[i], &already_seen, - request.mutable_proto_file()); + GetTransitiveDependencies(parsed_files[i], + true, // Include source code info. + &already_seen, request.mutable_proto_file()); } // Invoke the plugin. @@ -1180,14 +1327,14 @@ bool CommandLineInterface::GeneratePluginOutput( // We reset current_output to NULL first so that the old file is closed // before the new one is opened. current_output.reset(); - current_output.reset(output_directory->OpenForInsert( + current_output.reset(generator_context->OpenForInsert( output_file.name(), output_file.insertion_point())); } else if (!output_file.name().empty()) { // Starting a new file. Open it. // We reset current_output to NULL first so that the old file is closed // before the new one is opened. current_output.reset(); - current_output.reset(output_directory->Open(output_file.name())); + current_output.reset(generator_context->Open(output_file.name())); } else if (current_output == NULL) { *error = strings::Substitute( "$0: First file chunk returned by plugin did not specify a file name.", @@ -1281,12 +1428,17 @@ bool CommandLineInterface::WriteDescriptorSet( if (imports_in_descriptor_set_) { set already_seen; for (int i = 0; i < parsed_files.size(); i++) { - GetTransitiveDependencies( - parsed_files[i], &already_seen, file_set.mutable_file()); + GetTransitiveDependencies(parsed_files[i], + source_info_in_descriptor_set_, + &already_seen, file_set.mutable_file()); } } else { for (int i = 0; i < parsed_files.size(); i++) { - parsed_files[i]->CopyTo(file_set.add_file()); + FileDescriptorProto* file_proto = file_set.add_file(); + parsed_files[i]->CopyTo(file_proto); + if (source_info_in_descriptor_set_) { + parsed_files[i]->CopySourceCodeInfoTo(file_proto); + } } } @@ -1316,7 +1468,7 @@ bool CommandLineInterface::WriteDescriptorSet( } void CommandLineInterface::GetTransitiveDependencies( - const FileDescriptor* file, + const FileDescriptor* file, bool include_source_code_info, set* already_seen, RepeatedPtrField* output) { if (!already_seen->insert(file).second) { @@ -1326,13 +1478,125 @@ void CommandLineInterface::GetTransitiveDependencies( // Add all dependencies. for (int i = 0; i < file->dependency_count(); i++) { - GetTransitiveDependencies(file->dependency(i), already_seen, output); + GetTransitiveDependencies(file->dependency(i), include_source_code_info, + already_seen, output); } // Add this file. - file->CopyTo(output->Add()); + FileDescriptorProto* new_descriptor = output->Add(); + file->CopyTo(new_descriptor); + if (include_source_code_info) { + file->CopySourceCodeInfoTo(new_descriptor); + } +} + +namespace { + +// Utility function for PrintFreeFieldNumbers. +// Stores occupied ranges into the ranges parameter, and next level of sub +// message types into the nested_messages parameter. The FieldRange is left +// inclusive, right exclusive. i.e. [a, b). +// +// Nested Messages: +// Note that it only stores the nested message type, iff the nested type is +// either a direct child of the given descriptor, or the nested type is a +// decendent of the given descriptor and all the nodes between the +// nested type and the given descriptor are group types. e.g. +// +// message Foo { +// message Bar { +// message NestedBar {} +// } +// group Baz = 1 { +// group NestedBazGroup = 2 { +// message Quz { +// message NestedQuz {} +// } +// } +// message NestedBaz {} +// } +// } +// +// In this case, Bar, Quz and NestedBaz will be added into the nested types. +// Since free field numbers of group types will not be printed, this makes sure +// the nested message types in groups will not be dropped. The nested_messages +// parameter will contain the direct children (when groups are ignored in the +// tree) of the given descriptor for the caller to traverse. The declaration +// order of the nested messages is also preserved. +typedef pair FieldRange; +void GatherOccupiedFieldRanges(const Descriptor* descriptor, + set* ranges, + vector* nested_messages) { + set groups; + for (int i = 0; i < descriptor->field_count(); ++i) { + const FieldDescriptor* fd = descriptor->field(i); + ranges->insert(FieldRange(fd->number(), fd->number() + 1)); + if (fd->type() == FieldDescriptor::TYPE_GROUP) { + groups.insert(fd->message_type()); + } + } + for (int i = 0; i < descriptor->extension_range_count(); ++i) { + ranges->insert(FieldRange(descriptor->extension_range(i)->start, + descriptor->extension_range(i)->end)); + } + // Handle the nested messages/groups in declaration order to make it + // post-order strict. + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + const Descriptor* nested_desc = descriptor->nested_type(i); + if (groups.find(nested_desc) != groups.end()) { + GatherOccupiedFieldRanges(nested_desc, ranges, nested_messages); + } else { + nested_messages->push_back(nested_desc); + } + } } +// Utility function for PrintFreeFieldNumbers. +// Actually prints the formatted free field numbers for given message name and +// occupied ranges. +void FormatFreeFieldNumbers(const string& name, + const set& ranges) { + string output; + StringAppendF(&output, "%-35s free:", name.c_str()); + int next_free_number = 1; + for (set::const_iterator i = ranges.begin(); + i != ranges.end(); ++i) { + // This happens when groups re-use parent field numbers, in which + // case we skip the FieldRange entirely. + if (next_free_number >= i->second) continue; + + if (next_free_number < i->first) { + if (next_free_number + 1 == i->first) { + // Singleton + StringAppendF(&output, " %d", next_free_number); + } else { + // Range + StringAppendF(&output, " %d-%d", next_free_number, i->first - 1); + } + } + next_free_number = i->second; + } + if (next_free_number <= FieldDescriptor::kMaxNumber) { + StringAppendF(&output, " %d-INF", next_free_number); + } + cout << output << endl; +} + +} // namespace + +void CommandLineInterface::PrintFreeFieldNumbers( + const Descriptor* descriptor) { + set ranges; + vector nested_messages; + GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages); + + for (int i = 0; i < nested_messages.size(); ++i) { + PrintFreeFieldNumbers(nested_messages[i]); + } + FormatFreeFieldNumbers(descriptor->full_name(), ranges); +} + + } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index d25a50e..3b73415 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -48,15 +48,16 @@ namespace google { namespace protobuf { -class FileDescriptor; // descriptor.h +class Descriptor; // descriptor.h class DescriptorPool; // descriptor.h +class FileDescriptor; // descriptor.h class FileDescriptorProto; // descriptor.pb.h template class RepeatedPtrField; // repeated_field.h namespace compiler { class CodeGenerator; // code_generator.h -class OutputDirectory; // code_generator.h +class GeneratorContext; // code_generator.h class DiskSourceTree; // importer.h // This class implements the command-line interface to the protocol compiler. @@ -112,6 +113,19 @@ class LIBPROTOC_EXPORT CommandLineInterface { CodeGenerator* generator, const string& help_text); + // Register a code generator for a language. + // Besides flag_name you can specify another option_flag_name that could be + // used to pass extra parameters to the registered code generator. + // Suppose you have registered a generator by calling: + // command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...) + // Then you could invoke the compiler with a command like: + // protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz + // This will pass "enable_bar,enable_baz" as the parameter to the generator. + void RegisterGenerator(const string& flag_name, + const string& option_flag_name, + CodeGenerator* generator, + const string& help_text); + // Enables "plugins". In this mode, if a command-line flag ends with "_out" // but does not match any registered generator, the compiler will attempt to // find a "plugin" to implement the generator. Plugins are just executables. @@ -174,7 +188,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // ----------------------------------------------------------------- class ErrorPrinter; - class MemoryOutputDirectory; + class GeneratorContextImpl; class MemoryOutputStream; // Clear state from previous Run(). @@ -186,8 +200,15 @@ class LIBPROTOC_EXPORT CommandLineInterface { bool MakeInputsBeProtoPathRelative( DiskSourceTree* source_tree); + // Return status for ParseArguments() and InterpretArgument(). + enum ParseArgumentStatus { + PARSE_ARGUMENT_DONE_AND_CONTINUE, + PARSE_ARGUMENT_DONE_AND_EXIT, + PARSE_ARGUMENT_FAIL + }; + // Parse all command-line arguments. - bool ParseArguments(int argc, const char* const argv[]); + ParseArgumentStatus ParseArguments(int argc, const char* const argv[]); // Parses a command-line argument into a name/value pair. Returns // true if the next argument in the argv should be used as the value, @@ -203,7 +224,8 @@ class LIBPROTOC_EXPORT CommandLineInterface { bool ParseArgument(const char* arg, string* name, string* value); // Interprets arguments parsed with ParseArgument. - bool InterpretArgument(const string& name, const string& value); + ParseArgumentStatus InterpretArgument(const string& name, + const string& value); // Print the --help text to stderr. void PrintHelpText(); @@ -212,11 +234,11 @@ class LIBPROTOC_EXPORT CommandLineInterface { struct OutputDirective; // see below bool GenerateOutput(const vector& parsed_files, const OutputDirective& output_directive, - OutputDirectory* output_directory); + GeneratorContext* generator_context); bool GeneratePluginOutput(const vector& parsed_files, const string& plugin_name, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* generator_context, string* error); // Implements --encode and --decode. @@ -230,12 +252,30 @@ class LIBPROTOC_EXPORT CommandLineInterface { // protos will be ordered such that every file is listed before any file that // depends on it, so that you can call DescriptorPool::BuildFile() on them // in order. Any files in *already_seen will not be added, and each file - // added will be inserted into *already_seen. + // added will be inserted into *already_seen. If include_source_code_info is + // true then include the source code information in the FileDescriptorProtos. static void GetTransitiveDependencies( const FileDescriptor* file, + bool include_source_code_info, set* already_seen, RepeatedPtrField* output); + // Implements the --print_free_field_numbers. This function prints free field + // numbers into stdout for the message and it's nested message types in + // post-order, i.e. nested types first. Printed range are left-right + // inclusive, i.e. [a, b]. + // + // Groups: + // For historical reasons, groups are considered to share the same + // field number space with the parent message, thus it will not print free + // field numbers for groups. The field numbers used in the groups are + // excluded in the free field numbers of the parent message. + // + // Extension Ranges: + // Extension ranges are considered ocuppied field numbers and they will not be + // listed as free numbers in the output. + void PrintFreeFieldNumbers(const Descriptor* descriptor); + // ----------------------------------------------------------------- // The name of the executable as invoked (i.e. argv[0]). @@ -244,13 +284,21 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Version info set with SetVersionInfo(). string version_info_; - // Map from flag names to registered generators. + // Registered generators. struct GeneratorInfo { + string flag_name; + string option_flag_name; CodeGenerator* generator; string help_text; }; typedef map GeneratorMap; - GeneratorMap generators_; + GeneratorMap generators_by_flag_name_; + GeneratorMap generators_by_option_name_; + // A map from generator names to the parameters specified using the option + // flag. For example, if the user invokes the compiler with: + // protoc --foo_out=outputdir --foo_opt=enable_bar ... + // Then there will be an entry ("--foo_out", "enable_bar") in this map. + map generator_parameters_; // See AllowPlugins(). If this is empty, plugins aren't allowed. string plugin_prefix_; @@ -264,11 +312,19 @@ class LIBPROTOC_EXPORT CommandLineInterface { enum Mode { MODE_COMPILE, // Normal mode: parse .proto files and compile them. MODE_ENCODE, // --encode: read text from stdin, write binary to stdout. - MODE_DECODE // --decode: read binary from stdin, write text to stdout. + MODE_DECODE, // --decode: read binary from stdin, write text to stdout. + MODE_PRINT, // Print mode: print info of the given .proto files and exit. }; Mode mode_; + enum PrintMode { + PRINT_NONE, // Not in MODE_PRINT + PRINT_FREE_FIELDS, // --print_free_fields + }; + + PrintMode print_mode_; + enum ErrorFormat { ERROR_FORMAT_GCC, // GCC error output format (default). ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs). @@ -302,6 +358,10 @@ class LIBPROTOC_EXPORT CommandLineInterface { // the .proto files listed on the command-line are added. bool imports_in_descriptor_set_; + // True if --include_source_info was given, meaning that we should not strip + // SourceCodeInfo from the DescriptorSet. + bool source_info_in_descriptor_set_; + // Was the --disallow_services flag used? bool disallow_services_; diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 9129ebf..d20a214 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -40,6 +40,7 @@ #else #include #endif +#include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -121,6 +123,13 @@ class CommandLineInterfaceTest : public testing::Test { // substring. void ExpectErrorSubstring(const string& expected_substring); + // Like ExpectErrorSubstring, but checks that Run() returned zero. + void ExpectErrorSubstringWithZeroReturnCode( + const string& expected_substring); + + // Checks that the captured stdout is the same as the expected_text. + void ExpectCapturedStdout(const string& expected_text); + // Returns true if ExpectErrorSubstring(expected_substring) would pass, but // does not fail otherwise. bool HasAlternateErrorSubstring(const string& expected_substring); @@ -143,6 +152,10 @@ class CommandLineInterfaceTest : public testing::Test { const string& proto_name, const string& message_name, const string& output_directory); + void ExpectGeneratedWithMultipleInputs(const string& generator_name, + const string& all_proto_names, + const string& proto_name, + const string& message_name); void ExpectGeneratedWithInsertions(const string& generator_name, const string& parameter, const string& insertions, @@ -173,6 +186,9 @@ class CommandLineInterfaceTest : public testing::Test { // The captured stderr output. string error_text_; + // The captured stdout. + string captured_stdout_; + // Pointers which need to be deleted later. vector mock_generators_to_delete_; @@ -190,7 +206,7 @@ class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator { // implements CodeGenerator ---------------------------------------- bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { called_ = true; parameter_ = parameter; @@ -215,12 +231,12 @@ void CommandLineInterfaceTest::SetUp() { } // Create the temp directory. - GOOGLE_CHECK(File::CreateDir(temp_directory_.c_str(), DEFAULT_FILE_MODE)); + GOOGLE_CHECK_OK(File::CreateDir(temp_directory_, 0777)); // Register generators. CodeGenerator* generator = new MockCodeGenerator("test_generator"); mock_generators_to_delete_.push_back(generator); - cli_.RegisterGenerator("--test_out", generator, "Test output."); + cli_.RegisterGenerator("--test_out", "--test_opt", generator, "Test output."); cli_.RegisterGenerator("-t", generator, "Test output."); generator = new MockCodeGenerator("alt_generator"); @@ -246,12 +262,10 @@ void CommandLineInterfaceTest::TearDown() { } void CommandLineInterfaceTest::Run(const string& command) { - vector args; - SplitStringUsing(command, " ", &args); + vector args = Split(command, " ", true); if (!disallow_plugins_) { cli_.AllowPlugins("prefix-"); - const char* possible_paths[] = { // When building with shared libraries, libtool hides the real executable // in .libs and puts a fake wrapper in the current directory. @@ -287,18 +301,27 @@ void CommandLineInterfaceTest::Run(const string& command) { } } - scoped_array argv(new const char*[args.size()]); + scoped_array argv(new const char* [args.size()]); for (int i = 0; i < args.size(); i++) { args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true); argv[i] = args[i].c_str(); } + // TODO(jieluo): Cygwin doesn't work well if we try to capture stderr and + // stdout at the same time. Need to figure out why and add this capture back + // for Cygwin. +#if !defined(__CYGWIN__) + CaptureTestStdout(); +#endif CaptureTestStderr(); return_code_ = cli_.Run(args.size(), argv.get()); error_text_ = GetCapturedTestStderr(); +#if !defined(__CYGWIN__) + captured_stdout_ = GetCapturedTestStdout(); +#endif } // ------------------------------------------------------------------- @@ -310,16 +333,20 @@ void CommandLineInterfaceTest::CreateTempFile( string::size_type slash_pos = name.find_last_of('/'); if (slash_pos != string::npos) { string dir = name.substr(0, slash_pos); - File::RecursivelyCreateDir(temp_directory_ + "/" + dir, 0777); + if (!File::Exists(temp_directory_ + "/" + dir)) { + GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + dir, + 0777)); + } } // Write file. string full_name = temp_directory_ + "/" + name; - File::WriteStringToFileOrDie(contents, full_name); + GOOGLE_CHECK_OK(File::SetContents(full_name, contents, true)); } void CommandLineInterfaceTest::CreateTempDir(const string& name) { - File::RecursivelyCreateDir(temp_directory_ + "/" + name, 0777); + GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + name, + 0777)); } // ------------------------------------------------------------------- @@ -341,6 +368,12 @@ void CommandLineInterfaceTest::ExpectErrorSubstring( EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_); } +void CommandLineInterfaceTest::ExpectErrorSubstringWithZeroReturnCode( + const string& expected_substring) { + EXPECT_EQ(0, return_code_); + EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_); +} + bool CommandLineInterfaceTest::HasAlternateErrorSubstring( const string& expected_substring) { EXPECT_NE(0, return_code_); @@ -353,7 +386,8 @@ void CommandLineInterfaceTest::ExpectGenerated( const string& proto_name, const string& message_name) { MockCodeGenerator::ExpectGenerated( - generator_name, parameter, "", proto_name, message_name, temp_directory_); + generator_name, parameter, "", proto_name, message_name, proto_name, + temp_directory_); } void CommandLineInterfaceTest::ExpectGenerated( @@ -363,10 +397,21 @@ void CommandLineInterfaceTest::ExpectGenerated( const string& message_name, const string& output_directory) { MockCodeGenerator::ExpectGenerated( - generator_name, parameter, "", proto_name, message_name, + generator_name, parameter, "", proto_name, message_name, proto_name, temp_directory_ + "/" + output_directory); } +void CommandLineInterfaceTest::ExpectGeneratedWithMultipleInputs( + const string& generator_name, + const string& all_proto_names, + const string& proto_name, + const string& message_name) { + MockCodeGenerator::ExpectGenerated( + generator_name, "", "", proto_name, message_name, + all_proto_names, + temp_directory_); +} + void CommandLineInterfaceTest::ExpectGeneratedWithInsertions( const string& generator_name, const string& parameter, @@ -375,7 +420,7 @@ void CommandLineInterfaceTest::ExpectGeneratedWithInsertions( const string& message_name) { MockCodeGenerator::ExpectGenerated( generator_name, parameter, insertions, proto_name, message_name, - temp_directory_); + proto_name, temp_directory_); } void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled( @@ -388,14 +433,18 @@ void CommandLineInterfaceTest::ReadDescriptorSet( const string& filename, FileDescriptorSet* descriptor_set) { string path = temp_directory_ + "/" + filename; string file_contents; - if (!File::ReadFileToString(path, &file_contents)) { - FAIL() << "File not found: " << path; - } + GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true)); + if (!descriptor_set->ParseFromString(file_contents)) { FAIL() << "Could not parse file contents: " << path; } } +void CommandLineInterfaceTest::ExpectCapturedStdout( + const string& expected_text) { + EXPECT_EQ(expected_text, captured_stdout_); +} + // =================================================================== TEST_F(CommandLineInterfaceTest, BasicOutput) { @@ -455,8 +504,44 @@ TEST_F(CommandLineInterfaceTest, MultipleInputs) { "--proto_path=$tmpdir foo.proto bar.proto"); ExpectNoErrors(); - ExpectGenerated("test_generator", "", "foo.proto", "Foo"); - ExpectGenerated("test_generator", "", "bar.proto", "Bar"); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "bar.proto", "Bar"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "bar.proto", "Bar"); +} + +TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) { + // Test parsing multiple input files with an import of a separate file. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"baz.proto\";\n" + "message Bar {\n" + " optional Baz a = 1;\n" + "}\n"); + CreateTempFile("baz.proto", + "syntax = \"proto2\";\n" + "message Baz {}\n"); + + Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " + "--proto_path=$tmpdir foo.proto bar.proto"); + + ExpectNoErrors(); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "bar.proto", "Bar"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "bar.proto", "Bar"); } TEST_F(CommandLineInterfaceTest, CreateDirectory) { @@ -492,6 +577,32 @@ TEST_F(CommandLineInterfaceTest, GeneratorParameters) { ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo"); } +TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) { + // Test that generator parameters specified with the option flag are + // correctly passed to the code generator. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + // Create the "a" and "b" sub-directories. + CreateTempDir("a"); + CreateTempDir("b"); + + Run("protocol_compiler " + "--test_opt=foo1 " + "--test_out=bar:$tmpdir/a " + "--test_opt=foo2 " + "--test_out=baz:$tmpdir/b " + "--test_opt=foo3 " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGenerated( + "test_generator", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a"); + ExpectGenerated( + "test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b"); +} + TEST_F(CommandLineInterfaceTest, Insert) { // Test running a generator that inserts code into another's output. @@ -515,7 +626,7 @@ TEST_F(CommandLineInterfaceTest, Insert) { "foo.proto", "Foo"); } -#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(_WIN32) TEST_F(CommandLineInterfaceTest, WindowsOutputPath) { // Test that the output path can be a Windows-style path. @@ -725,8 +836,35 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) { FileDescriptorSet descriptor_set; ReadDescriptorSet("descriptor_set", &descriptor_set); if (HasFatalFailure()) return; - ASSERT_EQ(1, descriptor_set.file_size()); + EXPECT_EQ(1, descriptor_set.file_size()); EXPECT_EQ("bar.proto", descriptor_set.file(0).name()); + // Descriptor set should not have source code info. + EXPECT_FALSE(descriptor_set.file(0).has_source_code_info()); +} + +TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " + "--include_source_info --proto_path=$tmpdir bar.proto"); + + ExpectNoErrors(); + + FileDescriptorSet descriptor_set; + ReadDescriptorSet("descriptor_set", &descriptor_set); + if (HasFatalFailure()) return; + EXPECT_EQ(1, descriptor_set.file_size()); + EXPECT_EQ("bar.proto", descriptor_set.file(0).name()); + // Source code info included. + EXPECT_TRUE(descriptor_set.file(0).has_source_code_info()); } TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) { @@ -748,13 +886,47 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) { FileDescriptorSet descriptor_set; ReadDescriptorSet("descriptor_set", &descriptor_set); if (HasFatalFailure()) return; - ASSERT_EQ(2, descriptor_set.file_size()); + EXPECT_EQ(2, descriptor_set.file_size()); if (descriptor_set.file(0).name() == "bar.proto") { std::swap(descriptor_set.mutable_file()->mutable_data()[0], descriptor_set.mutable_file()->mutable_data()[1]); } EXPECT_EQ("foo.proto", descriptor_set.file(0).name()); EXPECT_EQ("bar.proto", descriptor_set.file(1).name()); + // Descriptor set should not have source code info. + EXPECT_FALSE(descriptor_set.file(0).has_source_code_info()); + EXPECT_FALSE(descriptor_set.file(1).has_source_code_info()); +} + +TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " + "--include_imports --include_source_info --proto_path=$tmpdir bar.proto"); + + ExpectNoErrors(); + + FileDescriptorSet descriptor_set; + ReadDescriptorSet("descriptor_set", &descriptor_set); + if (HasFatalFailure()) return; + EXPECT_EQ(2, descriptor_set.file_size()); + if (descriptor_set.file(0).name() == "bar.proto") { + std::swap(descriptor_set.mutable_file()->mutable_data()[0], + descriptor_set.mutable_file()->mutable_data()[1]); + } + EXPECT_EQ("foo.proto", descriptor_set.file(0).name()); + EXPECT_EQ("bar.proto", descriptor_set.file(1).name()); + // Source code info included. + EXPECT_TRUE(descriptor_set.file(0).has_source_code_info()); + EXPECT_TRUE(descriptor_set.file(1).has_source_code_info()); } // ------------------------------------------------------------------- @@ -1077,6 +1249,17 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) { #endif } +TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message MockCodeGenerator_HasSourceCodeInfo {}\n"); + + Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto"); + + ExpectErrorSubstring( + "Saw message type MockCodeGenerator_HasSourceCodeInfo: 1."); +} + TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) { // Test what happens if the plugin isn't found. @@ -1089,9 +1272,8 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) { "--proto_path=$tmpdir error.proto"); #ifdef _WIN32 - ExpectErrorSubstring( - "--badplug_out: prefix-gen-badplug: The system cannot find the file " - "specified."); + ExpectErrorSubstring("--badplug_out: prefix-gen-badplug: " + + Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND)); #else // Error written to stdout by child process after exec() fails. ExpectErrorSubstring( @@ -1120,11 +1302,11 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) { TEST_F(CommandLineInterfaceTest, HelpText) { Run("test_exec_name --help"); - ExpectErrorSubstring("Usage: test_exec_name "); - ExpectErrorSubstring("--test_out=OUT_DIR"); - ExpectErrorSubstring("Test output."); - ExpectErrorSubstring("--alt_out=OUT_DIR"); - ExpectErrorSubstring("Alt output."); + ExpectErrorSubstringWithZeroReturnCode("Usage: test_exec_name "); + ExpectErrorSubstringWithZeroReturnCode("--test_out=OUT_DIR"); + ExpectErrorSubstringWithZeroReturnCode("Test output."); + ExpectErrorSubstringWithZeroReturnCode("--alt_out=OUT_DIR"); + ExpectErrorSubstringWithZeroReturnCode("Alt output."); } TEST_F(CommandLineInterfaceTest, GccFormatErrors) { @@ -1153,7 +1335,7 @@ TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) { "--proto_path=$tmpdir --error_format=msvs foo.proto"); ExpectErrorText( - "foo.proto(2) : error in column=1: Expected top-level statement " + "$tmpdir/foo.proto(2) : error in column=1: Expected top-level statement " "(e.g. \"message\").\n"); } @@ -1234,6 +1416,76 @@ TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) { ExpectErrorText("Missing value for flag: --test_out\n"); } +TEST_F(CommandLineInterfaceTest, PrintFreeFieldNumbers) { + CreateTempFile( + "foo.proto", + "syntax = \"proto2\";\n" + "package foo;\n" + "message Foo {\n" + " optional int32 a = 2;\n" + " optional string b = 4;\n" + " optional string c = 5;\n" + " optional int64 d = 8;\n" + " optional double e = 10;\n" + "}\n"); + CreateTempFile( + "bar.proto", + "syntax = \"proto2\";\n" + "message Bar {\n" + " optional int32 a = 2;\n" + " extensions 4 to 5;\n" + " optional int64 d = 8;\n" + " extensions 10;\n" + "}\n"); + CreateTempFile( + "baz.proto", + "syntax = \"proto2\";\n" + "message Baz {\n" + " optional int32 a = 2;\n" + " optional int64 d = 8;\n" + " extensions 15 to max;\n" // unordered. + " extensions 13;\n" + " extensions 10 to 12;\n" + " extensions 5;\n" + " extensions 4;\n" + "}\n"); + CreateTempFile( + "quz.proto", + "syntax = \"proto2\";\n" + "message Quz {\n" + " message Foo {}\n" // nested message + " optional int32 a = 2;\n" + " optional group C = 4 {\n" + " optional int32 d = 5;\n" + " }\n" + " extensions 8 to 10;\n" + " optional group E = 11 {\n" + " optional int32 f = 9;\n" // explicitly reuse extension range 8-10 + " optional group G = 15 {\n" // nested group + " message Foo {}\n" // nested message inside nested group + " }\n" + " }\n" + "}\n"); + + Run("protocol_compiler --print_free_field_numbers --proto_path=$tmpdir " + "foo.proto bar.proto baz.proto quz.proto"); + + ExpectNoErrors(); + + // TODO(jieluo): Cygwin doesn't work well if we try to capture stderr and + // stdout at the same time. Need to figure out why and add this test back + // for Cygwin. +#if !defined(__CYGWIN__) + ExpectCapturedStdout( + "foo.Foo free: 1 3 6-7 9 11-INF\n" + "Bar free: 1 3 6-7 9 11-INF\n" + "Baz free: 1 3 6-7 9 14\n" + "Quz.Foo free: 1-INF\n" + "Quz.E.G.Foo free: 1-INF\n" + "Quz free: 1 3 6-7 12-14 16-INF\n"); +#endif +} + // =================================================================== // Test for --encode and --decode. Note that it would be easier to do this @@ -1253,7 +1505,7 @@ class EncodeDecodeTest : public testing::Test { void RedirectStdinFromText(const string& input) { string filename = TestTempDir() + "/test_stdin"; - File::WriteStringToFileOrDie(input, filename); + GOOGLE_CHECK_OK(File::SetContents(filename, input, true)); GOOGLE_CHECK(RedirectStdinFromFile(filename)); } @@ -1287,7 +1539,7 @@ class EncodeDecodeTest : public testing::Test { SplitStringUsing(command, " ", &args); args.push_back("--proto_path=" + TestSourceDir()); - scoped_array argv(new const char*[args.size()]); + scoped_array argv(new const char* [args.size()]); for (int i = 0; i < args.size(); i++) { argv[i] = args[i].c_str(); } @@ -1308,7 +1560,7 @@ class EncodeDecodeTest : public testing::Test { void ExpectStdoutMatchesBinaryFile(const string& filename) { string expected_output; - ASSERT_TRUE(File::ReadFileToString(filename, &expected_output)); + GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true)); // Don't use EXPECT_EQ because we don't want to print raw binary data to // stdout on failure. @@ -1317,7 +1569,7 @@ class EncodeDecodeTest : public testing::Test { void ExpectStdoutMatchesTextFile(const string& filename) { string expected_output; - ASSERT_TRUE(File::ReadFileToString(filename, &expected_output)); + GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true)); ExpectStdoutMatchesText(expected_output); } @@ -1337,22 +1589,23 @@ class EncodeDecodeTest : public testing::Test { }; TEST_F(EncodeDecodeTest, Encode) { - RedirectStdinFromFile(TestSourceDir() + - "/google/protobuf/testdata/text_format_unittest_data.txt"); + RedirectStdinFromFile(TestSourceDir() + "/google/protobuf/" + "testdata/text_format_unittest_data_oneof_implemented.txt"); EXPECT_TRUE(Run("google/protobuf/unittest.proto " "--encode=protobuf_unittest.TestAllTypes")); ExpectStdoutMatchesBinaryFile(TestSourceDir() + - "/google/protobuf/testdata/golden_message"); + "/google/protobuf/testdata/golden_message_oneof_implemented"); ExpectStderrMatchesText(""); } TEST_F(EncodeDecodeTest, Decode) { RedirectStdinFromFile(TestSourceDir() + - "/google/protobuf/testdata/golden_message"); + "/google/protobuf/testdata/golden_message_oneof_implemented"); EXPECT_TRUE(Run("google/protobuf/unittest.proto " "--decode=protobuf_unittest.TestAllTypes")); ExpectStdoutMatchesTextFile(TestSourceDir() + - "/google/protobuf/testdata/text_format_unittest_data.txt"); + "/google/protobuf/" + "testdata/text_format_unittest_data_oneof_implemented.txt"); ExpectStderrMatchesText(""); } diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc index 30b1d2b..48da534 100644 --- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc @@ -48,8 +48,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -79,10 +79,10 @@ class MockErrorCollector : public MultiFileErrorCollector { } }; -class MockOutputDirectory : public OutputDirectory { +class MockGeneratorContext : public GeneratorContext { public: - MockOutputDirectory() {} - ~MockOutputDirectory() { + MockGeneratorContext() {} + ~MockGeneratorContext() { STLDeleteValues(&files_); } @@ -93,16 +93,16 @@ class MockOutputDirectory : public OutputDirectory { << "Generator failed to generate file: " << virtual_filename; string actual_contents; - File::ReadFileToStringOrDie( - TestSourceDir() + "/" + physical_filename, - &actual_contents); + GOOGLE_CHECK_OK( + File::GetContents(TestSourceDir() + "/" + physical_filename, + &actual_contents, true)); EXPECT_TRUE(actual_contents == *expected_contents) << physical_filename << " needs to be regenerated. Please run " "generate_descriptor_proto.sh and add this file " "to your CL."; } - // implements OutputDirectory -------------------------------------- + // implements GeneratorContext -------------------------------------- virtual io::ZeroCopyOutputStream* Open(const string& filename) { string** map_slot = &files_[filename]; @@ -130,24 +130,24 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) { ASSERT_TRUE(plugin_proto_file != NULL); CppGenerator generator; - MockOutputDirectory output_directory; + MockGeneratorContext context; string error; string parameter; parameter = "dllexport_decl=LIBPROTOBUF_EXPORT"; ASSERT_TRUE(generator.Generate(proto_file, parameter, - &output_directory, &error)); + &context, &error)); parameter = "dllexport_decl=LIBPROTOC_EXPORT"; ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter, - &output_directory, &error)); - - output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.h", - "google/protobuf/descriptor.pb.h"); - output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.cc", - "google/protobuf/descriptor.pb.cc"); - output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h", - "google/protobuf/compiler/plugin.pb.h"); - output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc", - "google/protobuf/compiler/plugin.pb.cc"); + &context, &error)); + + context.ExpectFileMatches("google/protobuf/descriptor.pb.h", + "google/protobuf/descriptor.pb.h"); + context.ExpectFileMatches("google/protobuf/descriptor.pb.cc", + "google/protobuf/descriptor.pb.cc"); + context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h", + "google/protobuf/compiler/plugin.pb.h"); + context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc", + "google/protobuf/compiler/plugin.pb.cc"); } } // namespace diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 76d2b79..0c4796f 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -45,11 +45,27 @@ namespace protobuf { namespace compiler { namespace cpp { +namespace { +// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value +// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the +// generation of the GOOGLE_ARRAYSIZE constant. +bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { + int32 max_value = descriptor->value(0)->number(); + for (int i = 0; i < descriptor->value_count(); i++) { + if (descriptor->value(i)->number() > max_value) { + max_value = descriptor->value(i)->number(); + } + } + return max_value != kint32max; +} +} // namespace + EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, - const string& dllexport_decl) + const Options& options) : descriptor_(descriptor), classname_(ClassName(descriptor, false)), - dllexport_decl_(dllexport_decl) { + options_(options), + generate_array_size_(ShouldGenerateArraySize(descriptor)) { } EnumGenerator::~EnumGenerator() {} @@ -67,7 +83,10 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { for (int i = 0; i < descriptor_->value_count(); i++) { vars["name"] = descriptor_->value(i)->name(); - vars["number"] = SimpleItoa(descriptor_->value(i)->number()); + // In C++, an value of -2147483648 gets interpreted as the negative of + // 2147483648, and since 2147483648 can't fit in an integer, this produces a + // compiler warning. This works around that issue. + vars["number"] = Int32ToString(descriptor_->value(i)->number()); vars["prefix"] = (descriptor_->containing_type() == NULL) ? "" : classname_ + "_"; @@ -88,18 +107,22 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { vars["min_name"] = min_value->name(); vars["max_name"] = max_value->name(); - if (dllexport_decl_.empty()) { + if (options_.dllexport_decl.empty()) { vars["dllexport"] = ""; } else { - vars["dllexport"] = dllexport_decl_ + " "; + vars["dllexport"] = options_.dllexport_decl + " "; } printer->Print(vars, "$dllexport$bool $classname$_IsValid(int value);\n" "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n" - "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n" - "const int $prefix$$short_name$_ARRAYSIZE = $prefix$$short_name$_MAX + 1;\n" - "\n"); + "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"); + + if (generate_array_size_) { + printer->Print(vars, + "const int $prefix$$short_name$_ARRAYSIZE = " + "$prefix$$short_name$_MAX + 1;\n\n"); + } if (HasDescriptorMethods(descriptor_->file())) { printer->Print(vars, @@ -123,6 +146,7 @@ void EnumGenerator:: GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { if (HasDescriptorMethods(descriptor_->file())) { printer->Print( + "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type {};\n" "template <>\n" "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" " return $classname$_descriptor();\n" @@ -150,9 +174,12 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { "static const $nested_name$ $nested_name$_MIN =\n" " $classname$_$nested_name$_MIN;\n" "static const $nested_name$ $nested_name$_MAX =\n" - " $classname$_$nested_name$_MAX;\n" - "static const int $nested_name$_ARRAYSIZE =\n" - " $classname$_$nested_name$_ARRAYSIZE;\n"); + " $classname$_$nested_name$_MAX;\n"); + if (generate_array_size_) { + printer->Print(vars, + "static const int $nested_name$_ARRAYSIZE =\n" + " $classname$_$nested_name$_ARRAYSIZE;\n"); + } if (HasDescriptorMethods(descriptor_->file())) { printer->Print(vars, @@ -218,7 +245,7 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { iter != numbers.end(); ++iter) { printer->Print( " case $number$:\n", - "number", SimpleItoa(*iter)); + "number", Int32ToString(*iter)); } printer->Print(vars, @@ -245,8 +272,11 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { } printer->Print(vars, "const $classname$ $parent$::$nested_name$_MIN;\n" - "const $classname$ $parent$::$nested_name$_MAX;\n" - "const int $parent$::$nested_name$_ARRAYSIZE;\n"); + "const $classname$ $parent$::$nested_name$_MAX;\n"); + if (generate_array_size_) { + printer->Print(vars, + "const int $parent$::$nested_name$_ARRAYSIZE;\n"); + } printer->Print("#endif // _MSC_VER\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h index 58f7721..98cbdf6 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum.h @@ -36,8 +36,10 @@ #define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__ #include +#include #include + namespace google { namespace protobuf { namespace io { @@ -53,7 +55,7 @@ class EnumGenerator { public: // See generator.cc for the meaning of dllexport_decl. explicit EnumGenerator(const EnumDescriptor* descriptor, - const string& dllexport_decl); + const Options& options); ~EnumGenerator(); // Header stuff. @@ -86,7 +88,9 @@ class EnumGenerator { private: const EnumDescriptor* descriptor_; string classname_; - string dllexport_decl_; + Options options_; + // whether to generate the *_ARRAYSIZE constant. + bool generate_array_size_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index 91ce493..2723c04 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -46,11 +46,13 @@ namespace cpp { namespace { void SetEnumVariables(const FieldDescriptor* descriptor, - map* variables) { - SetCommonFieldVariables(descriptor, variables); + map* variables, + const Options& options) { + SetCommonFieldVariables(descriptor, variables, options); const EnumValueDescriptor* default_value = descriptor->default_value_enum(); (*variables)["type"] = ClassName(descriptor->enum_type(), true); - (*variables)["default"] = SimpleItoa(default_value->number()); + (*variables)["default"] = Int32ToString(default_value->number()); + (*variables)["full_name"] = descriptor->full_name(); } } // namespace @@ -58,9 +60,10 @@ void SetEnumVariables(const FieldDescriptor* descriptor, // =================================================================== EnumFieldGenerator:: -EnumFieldGenerator(const FieldDescriptor* descriptor) +EnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) : descriptor_(descriptor) { - SetEnumVariables(descriptor, &variables_); + SetEnumVariables(descriptor, &variables_, options); } EnumFieldGenerator::~EnumFieldGenerator() {} @@ -81,12 +84,14 @@ void EnumFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline $type$ $classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" " return static_cast< $type$ >($name$_);\n" "}\n" "inline void $classname$::set_$name$($type$ value) {\n" - " GOOGLE_DCHECK($type$_IsValid(value));\n" - " _set_bit($index$);\n" + " assert($type$_IsValid(value));\n" + " set_has_$name$();\n" " $name$_ = value;\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n"); } @@ -119,10 +124,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { " input, &value)));\n" "if ($type$_IsValid(value)) {\n" " set_$name$(static_cast< $type$ >(value));\n"); - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print(variables_, "} else {\n" " mutable_unknown_fields()->AddVarint($number$, value);\n"); + } else { + printer->Print( + "} else {\n" + " unknown_fields_stream.WriteVarint32(tag);\n" + " unknown_fields_stream.WriteVarint32(value);\n"); } printer->Print(variables_, "}\n"); @@ -151,10 +161,57 @@ GenerateByteSize(io::Printer* printer) const { // =================================================================== +EnumOneofFieldGenerator:: +EnumOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : EnumFieldGenerator(descriptor, options) { + SetCommonOneofFieldVariables(descriptor, &variables_); +} + +EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {} + +void EnumOneofFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$ $classname$::$name$() const {\n" + " if (has_$name$()) {\n" + " return static_cast< $type$ >($oneof_prefix$$name$_);\n" + " }\n" + " return static_cast< $type$ >($default$);\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n" + " assert($type$_IsValid(value));\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " }\n" + " $oneof_prefix$$name$_ = value;\n" + "}\n"); +} + +void EnumOneofFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n"); +} + +void EnumOneofFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + // Don't print any swapping code. Swapping the union will swap this field. +} + +void EnumOneofFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + printer->Print(variables_, + " $classname$_default_oneof_instance_->$name$_ = $default$;\n"); +} + +// =================================================================== + RepeatedEnumFieldGenerator:: -RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor) +RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) : descriptor_(descriptor) { - SetEnumVariables(descriptor, &variables_); + SetEnumVariables(descriptor, &variables_, options); } RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} @@ -163,7 +220,8 @@ void RepeatedEnumFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::RepeatedField $name$_;\n"); - if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) { + if (descriptor_->options().packed() + && HasGeneratedMethods(descriptor_->file())) { printer->Print(variables_, "mutable int _$name$_cached_byte_size_;\n"); } @@ -184,23 +242,28 @@ void RepeatedEnumFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline $type$ $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" " return static_cast< $type$ >($name$_.Get(index));\n" "}\n" "inline void $classname$::set_$name$(int index, $type$ value) {\n" - " GOOGLE_DCHECK($type$_IsValid(value));\n" + " assert($type$_IsValid(value));\n" " $name$_.Set(index, value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "inline void $classname$::add_$name$($type$ value) {\n" - " GOOGLE_DCHECK($type$_IsValid(value));\n" + " assert($type$_IsValid(value));\n" " $name$_.Add(value);\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n"); printer->Print(variables_, "inline const ::google::protobuf::RepeatedField&\n" "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" "inline ::google::protobuf::RepeatedField*\n" "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" "}\n"); } @@ -235,10 +298,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { " input, &value)));\n" "if ($type$_IsValid(value)) {\n" " add_$name$(static_cast< $type$ >(value));\n"); - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print(variables_, "} else {\n" " mutable_unknown_fields()->AddVarint($number$, value);\n"); + } else { + printer->Print( + "} else {\n" + " unknown_fields_stream.WriteVarint32(tag);\n" + " unknown_fields_stream.WriteVarint32(value);\n"); } printer->Print("}\n"); } @@ -345,7 +413,9 @@ GenerateByteSize(io::Printer* printer) const { " total_size += $tag_size$ +\n" " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n" "}\n" + "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" "_$name$_cached_byte_size_ = data_size;\n" + "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" "total_size += data_size;\n"); } else { printer->Print(variables_, diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h index 0793430..1da1623 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h @@ -46,7 +46,8 @@ namespace cpp { class EnumFieldGenerator : public FieldGenerator { public: - explicit EnumFieldGenerator(const FieldDescriptor* descriptor); + explicit EnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~EnumFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -62,16 +63,34 @@ class EnumFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); }; +class EnumOneofFieldGenerator : public EnumFieldGenerator { + public: + explicit EnumOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~EnumOneofFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator); +}; + class RepeatedEnumFieldGenerator : public FieldGenerator { public: - explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor); + explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~RepeatedEnumFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc index 658a707..ef56b5e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_extension.cc +++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc @@ -57,9 +57,9 @@ string ExtendeeClassName(const FieldDescriptor* descriptor) { } // anonymous namespace ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor, - const string& dllexport_decl) + const Options& options) : descriptor_(descriptor), - dllexport_decl_(dllexport_decl) { + options_(options) { // Construct type_traits_. if (descriptor_->is_repeated()) { type_traits_ = "Repeated"; @@ -106,8 +106,8 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) { // export/import specifier. if (descriptor_->extension_scope() == NULL) { vars["qualifier"] = "extern"; - if (!dllexport_decl_.empty()) { - vars["qualifier"] = dllexport_decl_ + " " + vars["qualifier"]; + if (!options_.dllexport_decl.empty()) { + vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"]; } } else { vars["qualifier"] = "static"; diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.h b/src/google/protobuf/compiler/cpp/cpp_extension.h index 3068b09..50ad035 100644 --- a/src/google/protobuf/compiler/cpp/cpp_extension.h +++ b/src/google/protobuf/compiler/cpp/cpp_extension.h @@ -37,6 +37,7 @@ #include #include +#include namespace google { namespace protobuf { @@ -56,8 +57,8 @@ namespace cpp { class ExtensionGenerator { public: // See generator.cc for the meaning of dllexport_decl. - explicit ExtensionGenerator(const FieldDescriptor* descriptor, - const string& dllexport_decl); + explicit ExtensionGenerator(const FieldDescriptor* desycriptor, + const Options& options); ~ExtensionGenerator(); // Header stuff. @@ -72,7 +73,7 @@ class ExtensionGenerator { private: const FieldDescriptor* descriptor_; string type_traits_; - string dllexport_decl_; + Options options_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc index 103cac4..beea8ba 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_field.cc @@ -33,6 +33,8 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include + #include #include #include @@ -52,7 +54,8 @@ namespace cpp { using internal::WireFormat; void SetCommonFieldVariables(const FieldDescriptor* descriptor, - map* variables) { + map* variables, + const Options& options) { (*variables)["name"] = FieldName(descriptor); (*variables)["index"] = SimpleItoa(descriptor->index()); (*variables)["number"] = SimpleItoa(descriptor->number()); @@ -64,6 +67,13 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["deprecation"] = descriptor->options().deprecated() ? " PROTOBUF_DEPRECATED" : ""; + (*variables)["cppget"] = "Get"; +} + +void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor, + map* variables) { + (*variables)["oneof_prefix"] = descriptor->containing_oneof()->name() + "_."; + (*variables)["oneof_name"] = descriptor->containing_oneof()->name(); } FieldGenerator::~FieldGenerator() {} @@ -80,46 +90,63 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { } -FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) - : descriptor_(descriptor), - field_generators_( - new scoped_ptr[descriptor->field_count()]) { +FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, + const Options& options) + : descriptor_(descriptor), + field_generators_( + new scoped_ptr[descriptor->field_count()]) { // Construct all the FieldGenerators. for (int i = 0; i < descriptor->field_count(); i++) { - field_generators_[i].reset(MakeGenerator(descriptor->field(i))); + field_generators_[i].reset(MakeGenerator(descriptor->field(i), options)); } } -FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) { +FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, + const Options& options) { if (field->is_repeated()) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: - return new RepeatedMessageFieldGenerator(field); + return new RepeatedMessageFieldGenerator(field, options); case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // RepeatedStringFieldGenerator handles unknown ctypes. case FieldOptions::STRING: - return new RepeatedStringFieldGenerator(field); + return new RepeatedStringFieldGenerator(field, options); + } + case FieldDescriptor::CPPTYPE_ENUM: + return new RepeatedEnumFieldGenerator(field, options); + default: + return new RepeatedPrimitiveFieldGenerator(field, options); + } + } else if (field->containing_oneof()) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_MESSAGE: + return new MessageOneofFieldGenerator(field, options); + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // StringOneofFieldGenerator handles unknown ctypes. + case FieldOptions::STRING: + return new StringOneofFieldGenerator(field, options); } case FieldDescriptor::CPPTYPE_ENUM: - return new RepeatedEnumFieldGenerator(field); + return new EnumOneofFieldGenerator(field, options); default: - return new RepeatedPrimitiveFieldGenerator(field); + return new PrimitiveOneofFieldGenerator(field, options); } } else { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: - return new MessageFieldGenerator(field); + return new MessageFieldGenerator(field, options); case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // StringFieldGenerator handles unknown ctypes. case FieldOptions::STRING: - return new StringFieldGenerator(field); + return new StringFieldGenerator(field, options); } case FieldDescriptor::CPPTYPE_ENUM: - return new EnumFieldGenerator(field); + return new EnumFieldGenerator(field, options); default: - return new PrimitiveFieldGenerator(field); + return new PrimitiveFieldGenerator(field, options); } } } diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index c303a33..e434067 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -36,10 +36,11 @@ #define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__ #include +#include #include -#include #include +#include namespace google { namespace protobuf { @@ -57,7 +58,11 @@ namespace cpp { // ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size', // 'deprecation']. void SetCommonFieldVariables(const FieldDescriptor* descriptor, - map* variables); + map* variables, + const Options& options); + +void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor, + map* variables); class FieldGenerator { public: @@ -69,6 +74,11 @@ class FieldGenerator { // class. virtual void GeneratePrivateMembers(io::Printer* printer) const = 0; + // Generate static default variable for this field. These are placed inside + // the message class. Most field types don't need this, so the default + // implementation is empty. + virtual void GenerateStaticMembers(io::Printer* printer) const {} + // Generate prototypes for all of the accessor functions related to this // field. These are placed inside the class definition. virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0; @@ -114,6 +124,13 @@ class FieldGenerator { // Most field types don't need this, so the default implementation is empty. virtual void GenerateDestructorCode(io::Printer* printer) const {} + // Generate code that allocates the fields's default instance. + virtual void GenerateDefaultInstanceAllocator(io::Printer* printer) const {} + + // Generate code that should be run when ShutdownProtobufLibrary() is called, + // to delete all dynamically-allocated objects. + virtual void GenerateShutdownCode(io::Printer* printer) const {} + // Generate lines to decode this field, which will be placed inside the // message's MergeFromCodedStream() method. virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0; @@ -144,7 +161,7 @@ class FieldGenerator { // Convenience class which constructs FieldGenerators for a Descriptor. class FieldGeneratorMap { public: - explicit FieldGeneratorMap(const Descriptor* descriptor); + explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options); ~FieldGeneratorMap(); const FieldGenerator& get(const FieldDescriptor* field) const; @@ -153,7 +170,8 @@ class FieldGeneratorMap { const Descriptor* descriptor_; scoped_array > field_generators_; - static FieldGenerator* MakeGenerator(const FieldDescriptor* field); + static FieldGenerator* MakeGenerator(const FieldDescriptor* field, + const Options& options); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index 80da7e4..f7f2cdd 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -33,6 +33,9 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include +#include + #include #include #include @@ -50,37 +53,36 @@ namespace cpp { // =================================================================== -FileGenerator::FileGenerator(const FileDescriptor* file, - const string& dllexport_decl) - : file_(file), - message_generators_( - new scoped_ptr[file->message_type_count()]), - enum_generators_( - new scoped_ptr[file->enum_type_count()]), - service_generators_( - new scoped_ptr[file->service_count()]), - extension_generators_( - new scoped_ptr[file->extension_count()]), - dllexport_decl_(dllexport_decl) { +FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) + : file_(file), + message_generators_( + new scoped_ptr[file->message_type_count()]), + enum_generators_( + new scoped_ptr[file->enum_type_count()]), + service_generators_( + new scoped_ptr[file->service_count()]), + extension_generators_( + new scoped_ptr[file->extension_count()]), + options_(options) { for (int i = 0; i < file->message_type_count(); i++) { message_generators_[i].reset( - new MessageGenerator(file->message_type(i), dllexport_decl)); + new MessageGenerator(file->message_type(i), options)); } for (int i = 0; i < file->enum_type_count(); i++) { enum_generators_[i].reset( - new EnumGenerator(file->enum_type(i), dllexport_decl)); + new EnumGenerator(file->enum_type(i), options)); } for (int i = 0; i < file->service_count(); i++) { service_generators_[i].reset( - new ServiceGenerator(file->service(i), dllexport_decl)); + new ServiceGenerator(file->service(i), options)); } for (int i = 0; i < file->extension_count(); i++) { extension_generators_[i].reset( - new ExtensionGenerator(file->extension(i), dllexport_decl)); + new ExtensionGenerator(file->extension(i), options)); } SplitStringUsing(file_->package(), ".", &package_parts_); @@ -104,6 +106,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { "filename", file_->name(), "filename_identifier", filename_identifier); + printer->Print( "#include \n" "\n"); @@ -128,13 +131,23 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { // OK, it's now safe to #include other files. printer->Print( - "#include \n" + "#include \n"); + if (file_->message_type_count() > 0) { + if (HasDescriptorMethods(file_)) { + printer->Print( + "#include \n"); + } else { + printer->Print( + "#include \n"); + } + } + printer->Print( "#include \n" "#include \n"); - if (HasDescriptorMethods(file_)) { + if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) { printer->Print( - "#include \n"); + "#include \n"); } if (HasGenericServices(file_)) { @@ -142,16 +155,32 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { "#include \n"); } + if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { + printer->Print( + "#include \n"); + } + + + set 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 string& name = file_->dependency(i)->name(); + bool public_import = (public_import_names.count(name) != 0); + + printer->Print( - "#include \"$dependency$.pb.h\"\n", - "dependency", StripProto(file_->dependency(i)->name())); + "#include \"$dependency$.pb.h\"$iwyu$\n", + "dependency", StripProto(name), + "iwyu", (public_import) ? " // IWYU pragma: export" : ""); } printer->Print( "// @@protoc_insertion_point(includes)\n"); + // Open namespace. GenerateNamespaceOpeners(printer); @@ -162,7 +191,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { "// Internal implementation detail -- do not call these.\n" "void $dllexport_decl$ $adddescriptorsname$();\n", "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), - "dllexport_decl", dllexport_decl_); + "dllexport_decl", options_.dllexport_decl); printer->Print( // Note that we don't put dllexport_decl on these because they are only @@ -230,6 +259,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { printer->Print(kThickSeparator); printer->Print("\n"); + // Generate class inline methods. for (int i = 0; i < file_->message_type_count(); i++) { if (i > 0) { @@ -282,20 +312,33 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { void FileGenerator::GenerateSource(io::Printer* printer) { printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" "\n" + // The generated code calls accessors that might be deprecated. We don't // want the compiler to warn in generated code. "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n" "#include \"$basename$.pb.h\"\n" - + "\n" + "#include \n" // for swap() + "\n" + "#include \n" "#include \n" "#include \n" "#include \n", + "filename", file_->name(), "basename", StripProto(file_->name())); + // Unknown fields implementation in lite mode uses StringOutputStream + if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { + printer->Print( + "#include \n"); + } + if (HasDescriptorMethods(file_)) { printer->Print( "#include \n" + "#include \n" "#include \n" "#include \n"); } @@ -378,11 +421,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) { void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // AddDescriptors() is a file-level procedure which adds the encoded - // FileDescriptorProto for this .proto file to the global DescriptorPool - // for generated files (DescriptorPool::generated_pool()). It always runs - // at static initialization time, so all files will be registered before - // main() starts. This procedure also constructs default instances and - // registers extensions. + // FileDescriptorProto for this .proto file to the global DescriptorPool for + // generated files (DescriptorPool::generated_pool()). It either runs at + // static initialization time (by default) or when default_instance() is + // called for the first time (in LITE_RUNTIME mode with + // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also + // constructs default instances and registers extensions. // // Its sibling, AssignDescriptors(), actually pulls the compiled // FileDescriptor from the DescriptorPool and uses it to populate all of @@ -486,22 +530,29 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { printer->Outdent(); printer->Print( - "}\n"); + "}\n\n"); // ----------------------------------------------------------------- // Now generate the AddDescriptors() function. - printer->Print( - "\n" + PrintHandlingOptionalStaticInitializers( + file_, printer, + // With static initializers. + // Note that we don't need any special synchronization in the following code + // because it is called at static init time before any threads exist. "void $adddescriptorsname$() {\n" - // We don't need any special synchronization here because this code is - // called at static init time before any threads exist. " static bool already_here = false;\n" " if (already_here) return;\n" " already_here = true;\n" " GOOGLE_PROTOBUF_VERIFY_VERSION;\n" "\n", + // Without. + "void $adddescriptorsname$_impl() {\n" + " GOOGLE_PROTOBUF_VERIFY_VERSION;\n" + "\n", + // Vars. "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); + printer->Indent(); // Call the AddDescriptors() methods for all of our dependencies, to make @@ -509,17 +560,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { for (int i = 0; i < file_->dependency_count(); i++) { const FileDescriptor* dependency = file_->dependency(i); // Print the namespace prefix for the dependency. - vector dependency_package_parts; - SplitStringUsing(dependency->package(), ".", &dependency_package_parts); - printer->Print("::"); - for (int i = 0; i < dependency_package_parts.size(); i++) { - printer->Print("$name$::", - "name", dependency_package_parts[i]); - } + string add_desc_name = QualifiedFileLevelSymbol( + dependency->package(), GlobalAddDescriptorsName(dependency->name())); // Call its AddDescriptors function. printer->Print( "$name$();\n", - "name", GlobalAddDescriptorsName(dependency->name())); + "name", add_desc_name); } if (HasDescriptorMethods(file_)) { @@ -538,10 +584,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { static const int kBytesPerLine = 40; for (int i = 0; i < file_data.size(); i += kBytesPerLine) { printer->Print("\n \"$data$\"", - "data", CEscape(file_data.substr(i, kBytesPerLine))); + "data", + EscapeTrigraphs( + CEscape(file_data.substr(i, kBytesPerLine)))); } printer->Print( - ", $size$);\n", + ", $size$);\n", "size", SimpleItoa(file_data.size())); // Call MessageFactory::InternalRegisterGeneratedFile(). @@ -569,17 +617,26 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { "shutdownfilename", GlobalShutdownFileName(file_->name())); printer->Outdent(); - printer->Print( "}\n" - "\n" + "\n"); + + PrintHandlingOptionalStaticInitializers( + file_, printer, + // With static initializers. "// Force AddDescriptors() to be called at static initialization time.\n" "struct StaticDescriptorInitializer_$filename$ {\n" " StaticDescriptorInitializer_$filename$() {\n" " $adddescriptorsname$();\n" " }\n" - "} static_descriptor_initializer_$filename$_;\n" - "\n", + "} static_descriptor_initializer_$filename$_;\n", + // Without. + "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n" + "void $adddescriptorsname$() {\n" + " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n" + " &$adddescriptorsname$_impl);\n" + "}\n", + // Vars. "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), "filename", FilenameIdentifier(file_->name())); } diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h index b4e0128..0797097 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.h +++ b/src/google/protobuf/compiler/cpp/cpp_file.h @@ -35,10 +35,12 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ +#include #include #include #include #include +#include namespace google { namespace protobuf { @@ -61,7 +63,7 @@ class FileGenerator { public: // See generator.cc for the meaning of dllexport_decl. explicit FileGenerator(const FileDescriptor* file, - const string& dllexport_decl); + const Options& options); ~FileGenerator(); void GenerateHeader(io::Printer* printer); @@ -84,8 +86,7 @@ class FileGenerator { // E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}. vector package_parts_; - - string dllexport_decl_; + const Options options_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc index d67d350..a43e993 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.cc +++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -53,7 +54,7 @@ CppGenerator::~CppGenerator() {} bool CppGenerator::Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* generator_context, string* error) const { vector > options; ParseGeneratorParameter(parameter, &options); @@ -78,11 +79,13 @@ bool CppGenerator::Generate(const FileDescriptor* file, // } // FOO_EXPORT is a macro which should expand to __declspec(dllexport) or // __declspec(dllimport) depending on what is being compiled. - string dllexport_decl; + Options file_options; for (int i = 0; i < options.size(); i++) { if (options[i].first == "dllexport_decl") { - dllexport_decl = options[i].second; + file_options.dllexport_decl = options[i].second; + } else if (options[i].first == "safe_boundary_check") { + file_options.safe_boundary_check = true; } else { *error = "Unknown generator option: " + options[i].first; return false; @@ -95,12 +98,12 @@ bool CppGenerator::Generate(const FileDescriptor* file, string basename = StripProto(file->name()); basename.append(".pb"); - FileGenerator file_generator(file, dllexport_decl); + FileGenerator file_generator(file, file_options); // Generate header. { scoped_ptr output( - output_directory->Open(basename + ".h")); + generator_context->Open(basename + ".h")); io::Printer printer(output.get(), '$'); file_generator.GenerateHeader(&printer); } @@ -108,7 +111,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, // Generate cc file. { scoped_ptr output( - output_directory->Open(basename + ".cc")); + generator_context->Open(basename + ".cc")); io::Printer printer(output.get(), '$'); file_generator.GenerateSource(&printer); } diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.h b/src/google/protobuf/compiler/cpp/cpp_generator.h index f52e886..a90e84d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.h +++ b/src/google/protobuf/compiler/cpp/cpp_generator.h @@ -57,7 +57,7 @@ class LIBPROTOC_EXPORT CppGenerator : public CodeGenerator { // implements CodeGenerator ---------------------------------------- bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* generator_context, string* error) const; private: diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index e3df88b..9ee8b6e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -33,10 +33,12 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include #include #include #include +#include #include #include #include @@ -80,6 +82,22 @@ hash_set MakeKeywordsMap() { hash_set kKeywords = MakeKeywordsMap(); +// Returns whether the provided descriptor has an extension. This includes its +// nested types. +bool HasExtension(const Descriptor* descriptor) { + if (descriptor->extension_count() > 0) { + return true; + } + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + if (HasExtension(descriptor->nested_type(i))) { + return true; + } + } + return false; +} + +} // namespace + string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { string result; // Note: I distrust ctype.h due to locales. @@ -105,8 +123,6 @@ string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { return result; } -} // namespace - const char kThickSeparator[] = "// ===================================================================\n"; const char kThinSeparator[] = @@ -132,7 +148,7 @@ string ClassName(const Descriptor* descriptor, bool qualified) { string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) { if (enum_descriptor->containing_type() == NULL) { if (qualified) { - return DotsToColons(enum_descriptor->full_name()); + return "::" + DotsToColons(enum_descriptor->full_name()); } else { return enum_descriptor->name(); } @@ -240,14 +256,35 @@ const char* DeclaredTypeMethodName(FieldDescriptor::Type type) { return ""; } +string Int32ToString(int number) { + // gcc rejects the decimal form of kint32min. + if (number == kint32min) { + GOOGLE_COMPILE_ASSERT(kint32min == (~0x7fffffff), kint32min_value_error); + return "(~0x7fffffff)"; + } else { + return SimpleItoa(number); + } +} + +string Int64ToString(int64 number) { + // gcc rejects the decimal form of kint64min + if (number == kint64min) { + // Make sure we are in a 2's complement system. + GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(~0x7fffffffffffffff), + kint64min_value_error); + return "GOOGLE_LONGLONG(~0x7fffffffffffffff)"; + } + return "GOOGLE_LONGLONG(" + SimpleItoa(number) + ")"; +} + string DefaultValue(const FieldDescriptor* field) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: - return SimpleItoa(field->default_value_int32()); + return Int32ToString(field->default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: return SimpleItoa(field->default_value_uint32()) + "u"; case FieldDescriptor::CPPTYPE_INT64: - return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")"; + return Int64ToString(field->default_value_int64()); case FieldDescriptor::CPPTYPE_UINT64: return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")"; case FieldDescriptor::CPPTYPE_DOUBLE: { @@ -290,9 +327,11 @@ string DefaultValue(const FieldDescriptor* field) { return strings::Substitute( "static_cast< $0 >($1)", ClassName(field->enum_type(), true), - field->default_value_enum()->number()); + Int32ToString(field->default_value_enum()->number())); case FieldDescriptor::CPPTYPE_STRING: - return "\"" + CEscape(field->default_value_string()) + "\""; + return "\"" + EscapeTrigraphs( + CEscape(field->default_value_string())) + + "\""; case FieldDescriptor::CPPTYPE_MESSAGE: return FieldMessageTypeName(field) + "::default_instance()"; } @@ -335,6 +374,120 @@ string GlobalShutdownFileName(const string& filename) { return "protobuf_ShutdownFile_" + FilenameIdentifier(filename); } +// Return the qualified C++ name for a file level symbol. +string QualifiedFileLevelSymbol(const string& package, const string& name) { + if (package.empty()) { + return StrCat("::", name); + } + return StrCat("::", DotsToColons(package), "::", name); +} + +// Escape C++ trigraphs by escaping question marks to \? +string EscapeTrigraphs(const string& to_escape) { + return StringReplace(to_escape, "?", "\\?", true); +} + +// Escaped function name to eliminate naming conflict. +string SafeFunctionName(const Descriptor* descriptor, + const FieldDescriptor* field, + const string& prefix) { + // Do not use FieldName() since it will escape keywords. + string name = field->name(); + LowerString(&name); + string function_name = prefix + name; + if (descriptor->FindFieldByName(function_name)) { + // Single underscore will also make it conflicting with the private data + // member. We use double underscore to escape function names. + function_name.append("__"); + } else if (kKeywords.count(name) > 0) { + // If the field name is a keyword, we append the underscore back to keep it + // consistent with other function names. + function_name.append("_"); + } + return function_name; +} + +bool StaticInitializersForced(const FileDescriptor* file) { + if (HasDescriptorMethods(file) || file->extension_count() > 0) { + return true; + } + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasExtension(file->message_type(i))) { + return true; + } + } + return false; +} + +void PrintHandlingOptionalStaticInitializers( + const FileDescriptor* file, io::Printer* printer, + const char* with_static_init, const char* without_static_init, + const char* var1, const string& val1, + const char* var2, const string& val2) { + map vars; + if (var1) { + vars[var1] = val1; + } + if (var2) { + vars[var2] = val2; + } + PrintHandlingOptionalStaticInitializers( + vars, file, printer, with_static_init, without_static_init); +} + +void PrintHandlingOptionalStaticInitializers( + const map& vars, const FileDescriptor* file, + io::Printer* printer, const char* with_static_init, + const char* without_static_init) { + if (StaticInitializersForced(file)) { + printer->Print(vars, with_static_init); + } else { + printer->Print(vars, (string( + "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n") + + without_static_init + + "#else\n" + + with_static_init + + "#endif\n").c_str()); + } +} + + +static bool HasEnumDefinitions(const Descriptor* message_type) { + if (message_type->enum_type_count() > 0) return true; + for (int i = 0; i < message_type->nested_type_count(); ++i) { + if (HasEnumDefinitions(message_type->nested_type(i))) return true; + } + return false; +} + +bool HasEnumDefinitions(const FileDescriptor* file) { + if (file->enum_type_count() > 0) return true; + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasEnumDefinitions(file->message_type(i))) return true; + } + return false; +} + +bool IsStringOrMessage(const FieldDescriptor* field) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_BOOL: + case FieldDescriptor::CPPTYPE_ENUM: + return false; + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + return true; + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; +} + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index f99b5fe..27444d5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -35,12 +35,18 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ +#include #include #include #include namespace google { namespace protobuf { + +namespace io { +class Printer; +} + namespace compiler { namespace cpp { @@ -97,6 +103,12 @@ const char* PrimitiveTypeName(FieldDescriptor::CppType type); // methods of WireFormat. For example, TYPE_INT32 becomes "Int32". const char* DeclaredTypeMethodName(FieldDescriptor::Type type); +// Return the code that evaluates to the number when compiled. +string Int32ToString(int number); + +// Return the code that evaluates to the number when compiled. +string Int64ToString(int64 number); + // Get code that evaluates to the field's default value. string DefaultValue(const FieldDescriptor* field); @@ -109,27 +121,43 @@ string GlobalAddDescriptorsName(const string& filename); // Return the name of the AssignDescriptors() function for a given file. string GlobalAssignDescriptorsName(const string& filename); +// Return the qualified C++ name for a file level symbol. +string QualifiedFileLevelSymbol(const string& package, const string& name); + // Return the name of the ShutdownFile() function for a given file. string GlobalShutdownFileName(const string& filename); -// Do message classes in this file keep track of unknown fields? -inline bool HasUnknownFields(const FileDescriptor *file) { +// Escape C++ trigraphs by escaping question marks to \? +string EscapeTrigraphs(const string& to_escape); + +// Escaped function name to eliminate naming conflict. +string SafeFunctionName(const Descriptor* descriptor, + const FieldDescriptor* field, + const string& prefix); + +// Do message classes in this file use UnknownFieldSet? +// Otherwise, messages will store unknown fields in a string +inline bool UseUnknownFieldSet(const FileDescriptor* file) { return file->options().optimize_for() != FileOptions::LITE_RUNTIME; } + +// Does this file have any enum type definitions? +bool HasEnumDefinitions(const FileDescriptor* file); + // Does this file have generated parsing, serialization, and other // standard methods for which reflection-based fallback implementations exist? -inline bool HasGeneratedMethods(const FileDescriptor *file) { +inline bool HasGeneratedMethods(const FileDescriptor* file) { return file->options().optimize_for() != FileOptions::CODE_SIZE; } -// Do message classes in this file have descriptor and refelction methods? -inline bool HasDescriptorMethods(const FileDescriptor *file) { +// Do message classes in this file have descriptor and reflection methods? +inline bool HasDescriptorMethods(const FileDescriptor* file) { return file->options().optimize_for() != FileOptions::LITE_RUNTIME; } // Should we generate generic services for this file? -inline bool HasGenericServices(const FileDescriptor *file) { +inline bool HasGenericServices(const FileDescriptor* file) { return file->service_count() > 0 && file->options().optimize_for() != FileOptions::LITE_RUNTIME && file->options().cc_generic_services(); @@ -147,6 +175,28 @@ inline bool HasFastArraySerialization(const FileDescriptor* file) { return file->options().optimize_for() == FileOptions::SPEED; } +// Returns whether we have to generate code with static initializers. +bool StaticInitializersForced(const FileDescriptor* file); + +// Prints 'with_static_init' if static initializers have to be used for the +// provided file. Otherwise emits both 'with_static_init' and +// 'without_static_init' using #ifdef. +void PrintHandlingOptionalStaticInitializers( + const FileDescriptor* file, io::Printer* printer, + const char* with_static_init, const char* without_static_init, + const char* var1 = NULL, const string& val1 = "", + const char* var2 = NULL, const string& val2 = ""); + +void PrintHandlingOptionalStaticInitializers( + const map& vars, const FileDescriptor* file, + io::Printer* printer, const char* with_static_init, + const char* without_static_init); + + +// Returns true if the field's CPPTYPE is string or message. +bool IsStringOrMessage(const FieldDescriptor* field); + +string UnderscoresToCamelCase(const string& input, bool cap_next_letter); } // namespace cpp } // namespace compiler diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index cbdcce8..962ff53 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -47,6 +50,7 @@ #include #include + namespace google { namespace protobuf { namespace compiler { @@ -72,15 +76,6 @@ struct FieldOrderingByNumber { } }; -const char* kWireTypeNames[] = { - "VARINT", - "FIXED64", - "LENGTH_DELIMITED", - "START_GROUP", - "END_GROUP", - "FIXED32", -}; - // Sort the fields of the given Descriptor by number into a new[]'d array // and return it. const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { @@ -102,6 +97,13 @@ struct ExtensionRangeSorter { } }; +// Returns true if the "required" restriction check should be ignored for the +// given field. +inline static bool ShouldIgnoreRequiredFieldCheck( + const FieldDescriptor* field) { + return false; +} + // Returns true if the message type has any required fields. If it doesn't, // we can optimize out calls to its IsInitialized() method. // @@ -128,7 +130,8 @@ static bool HasRequiredFields( if (field->is_required()) { return true; } - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !ShouldIgnoreRequiredFieldCheck(field)) { if (HasRequiredFields(field->message_type(), already_seen)) { return true; } @@ -143,36 +146,171 @@ static bool HasRequiredFields(const Descriptor* type) { return HasRequiredFields(type, &already_seen); } +// This returns an estimate of the compiler's alignment for the field. This +// can't guarantee to be correct because the generated code could be compiled on +// different systems with different alignment rules. The estimates below assume +// 64-bit pointers. +int EstimateAlignmentSize(const FieldDescriptor* field) { + if (field == NULL) return 0; + if (field->is_repeated()) return 8; + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_BOOL: + return 1; + + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_FLOAT: + return 4; + + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + return 8; + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return -1; // Make compiler happy. +} + +// FieldGroup is just a helper for OptimizePadding below. It holds a vector of +// fields that are grouped together because they have compatible alignment, and +// a preferred location in the final field ordering. +class FieldGroup { + public: + FieldGroup() + : preferred_location_(0) {} + + // A group with a single field. + FieldGroup(float preferred_location, const FieldDescriptor* field) + : preferred_location_(preferred_location), + fields_(1, field) {} + + // Append the fields in 'other' to this group. + void Append(const FieldGroup& other) { + if (other.fields_.empty()) { + return; + } + // Preferred location is the average among all the fields, so we weight by + // the number of fields on each FieldGroup object. + preferred_location_ = + (preferred_location_ * fields_.size() + + (other.preferred_location_ * other.fields_.size())) / + (fields_.size() + other.fields_.size()); + fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end()); + } + + void SetPreferredLocation(float location) { preferred_location_ = location; } + const vector& fields() const { return fields_; } + + // FieldGroup objects sort by their preferred location. + bool operator<(const FieldGroup& other) const { + return preferred_location_ < other.preferred_location_; + } + + private: + // "preferred_location_" is an estimate of where this group should go in the + // final list of fields. We compute this by taking the average index of each + // field in this group in the original ordering of fields. This is very + // approximate, but should put this group close to where its member fields + // originally went. + float preferred_location_; + vector fields_; + // We rely on the default copy constructor and operator= so this type can be + // used in a vector. +}; + +// Reorder 'fields' so that if the fields are output into a c++ class in the new +// order, the alignment padding is minimized. We try to do this while keeping +// each field as close as possible to its original position so that we don't +// reduce cache locality much for function that access each field in order. +void OptimizePadding(vector* fields) { + // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes. + vector aligned_to_1, aligned_to_4, aligned_to_8; + for (int i = 0; i < fields->size(); ++i) { + switch (EstimateAlignmentSize((*fields)[i])) { + case 1: aligned_to_1.push_back(FieldGroup(i, (*fields)[i])); break; + case 4: aligned_to_4.push_back(FieldGroup(i, (*fields)[i])); break; + case 8: aligned_to_8.push_back(FieldGroup(i, (*fields)[i])); break; + default: + GOOGLE_LOG(FATAL) << "Unknown alignment size."; + } + } + + // Now group fields aligned to 1 byte into sets of 4, and treat those like a + // single field aligned to 4 bytes. + for (int i = 0; i < aligned_to_1.size(); i += 4) { + FieldGroup field_group; + for (int j = i; j < aligned_to_1.size() && j < i + 4; ++j) { + field_group.Append(aligned_to_1[j]); + } + aligned_to_4.push_back(field_group); + } + // Sort by preferred location to keep fields as close to their original + // location as possible. Using stable_sort ensures that the output is + // consistent across runs. + stable_sort(aligned_to_4.begin(), aligned_to_4.end()); + + // Now group fields aligned to 4 bytes (or the 4-field groups created above) + // into pairs, and treat those like a single field aligned to 8 bytes. + for (int i = 0; i < aligned_to_4.size(); i += 2) { + FieldGroup field_group; + for (int j = i; j < aligned_to_4.size() && j < i + 2; ++j) { + field_group.Append(aligned_to_4[j]); + } + if (i == aligned_to_4.size() - 1) { + // Move incomplete 4-byte block to the end. + field_group.SetPreferredLocation(fields->size() + 1); + } + aligned_to_8.push_back(field_group); + } + // Sort by preferred location. + stable_sort(aligned_to_8.begin(), aligned_to_8.end()); + + // Now pull out all the FieldDescriptors in order. + fields->clear(); + for (int i = 0; i < aligned_to_8.size(); ++i) { + fields->insert(fields->end(), + aligned_to_8[i].fields().begin(), + aligned_to_8[i].fields().end()); + } +} + +string MessageTypeProtoName(const FieldDescriptor* field) { + return field->message_type()->full_name(); +} + } // =================================================================== MessageGenerator::MessageGenerator(const Descriptor* descriptor, - const string& dllexport_decl) - : descriptor_(descriptor), - classname_(ClassName(descriptor, false)), - dllexport_decl_(dllexport_decl), - field_generators_(descriptor), - nested_generators_(new scoped_ptr[ - descriptor->nested_type_count()]), - enum_generators_(new scoped_ptr[ - descriptor->enum_type_count()]), - extension_generators_(new scoped_ptr[ - descriptor->extension_count()]) { + const Options& options) + : descriptor_(descriptor), + classname_(ClassName(descriptor, false)), + options_(options), + field_generators_(descriptor, options), + nested_generators_(new scoped_ptr< + MessageGenerator>[descriptor->nested_type_count()]), + enum_generators_( + new scoped_ptr[descriptor->enum_type_count()]), + extension_generators_(new scoped_ptr< + ExtensionGenerator>[descriptor->extension_count()]) { for (int i = 0; i < descriptor->nested_type_count(); i++) { nested_generators_[i].reset( - new MessageGenerator(descriptor->nested_type(i), dllexport_decl)); + new MessageGenerator(descriptor->nested_type(i), options)); } for (int i = 0; i < descriptor->enum_type_count(); i++) { enum_generators_[i].reset( - new EnumGenerator(descriptor->enum_type(i), dllexport_decl)); + new EnumGenerator(descriptor->enum_type(i), options)); } for (int i = 0; i < descriptor->extension_count(); i++) { extension_generators_[i].reset( - new ExtensionGenerator(descriptor->extension(i), dllexport_decl)); + new ExtensionGenerator(descriptor->extension(i), options)); } } @@ -217,7 +355,7 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { PrintFieldComment(printer, field); map vars; - SetCommonFieldVariables(field, &vars); + SetCommonFieldVariables(field, &vars, options_); vars["constant_name"] = FieldConstantName(field); if (field->is_repeated()) { @@ -242,6 +380,14 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { "GOOGLE_PROTOBUF_EXTENSION_ACCESSORS($classname$)\n", "classname", classname_); } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "inline $camel_oneof_name$Case $oneof_name$_case() const;\n", + "camel_oneof_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true), + "oneof_name", descriptor_->oneof_decl(i)->name()); + } } void MessageGenerator:: @@ -254,7 +400,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { PrintFieldComment(printer, field); map vars; - SetCommonFieldVariables(field, &vars); + SetCommonFieldVariables(field, &vars, options_); // Generate has_$name$() or $name$_size(). if (field->is_repeated()) { @@ -262,12 +408,34 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { "inline int $classname$::$name$_size() const {\n" " return $name$_.size();\n" "}\n"); + } else if (field->containing_oneof()) { + // Singular field in a oneof + vars["field_name"] = UnderscoresToCamelCase(field->name(), true); + vars["oneof_name"] = field->containing_oneof()->name(); + vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); + printer->Print(vars, + "inline bool $classname$::has_$name$() const {\n" + " return $oneof_name$_case() == k$field_name$;\n" + "}\n" + "inline void $classname$::set_has_$name$() {\n" + " _oneof_case_[$oneof_index$] = k$field_name$;\n" + "}\n"); } else { // Singular field. + char buffer[kFastToBufferSize]; + vars["has_array_index"] = SimpleItoa(field->index() / 32); + vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), buffer); printer->Print(vars, "inline bool $classname$::has_$name$() const {\n" - " return _has_bit($index$);\n" - "}\n"); + " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" + "}\n" + "inline void $classname$::set_has_$name$() {\n" + " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" + "}\n" + "inline void $classname$::clear_has_$name$() {\n" + " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" + "}\n" + ); } // Generate clear_$name$() @@ -275,13 +443,27 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { "inline void $classname$::clear_$name$() {\n"); printer->Indent(); - field_generators_.get(field).GenerateClearingCode(printer); - printer->Outdent(); - if (!field->is_repeated()) { - printer->Print(vars, " _clear_bit($index$);\n"); + if (field->containing_oneof()) { + // Clear this field only if it is the active field in this oneof, + // otherwise ignore + printer->Print(vars, + "if (has_$name$()) {\n"); + printer->Indent(); + field_generators_.get(field).GenerateClearingCode(printer); + printer->Print(vars, + "clear_has_$oneof_name$();\n"); + printer->Outdent(); + printer->Print("}\n"); + } else { + field_generators_.get(field).GenerateClearingCode(printer); + if (!field->is_repeated()) { + printer->Print(vars, + "clear_has_$name$();\n"); + } } + printer->Outdent(); printer->Print("}\n"); // Generate type-specific accessors. @@ -289,6 +471,49 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { printer->Print("\n"); } + + // Generate has_$name$() and clear_has_$name$() functions for oneofs + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + map vars; + vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + vars["cap_oneof_name"] = + ToUpper(descriptor_->oneof_decl(i)->name()); + vars["classname"] = classname_; + printer->Print( + vars, + "inline bool $classname$::has_$oneof_name$() {\n" + " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" + "}\n" + "inline void $classname$::clear_has_$oneof_name$() {\n" + " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n" + "}\n"); + } +} + +// Helper for the code that emits the Clear() method. +static bool CanClearByZeroing(const FieldDescriptor* field) { + if (field->is_repeated() || field->is_extension()) return false; + switch (field->cpp_type()) { + case internal::WireFormatLite::CPPTYPE_ENUM: + return field->default_value_enum()->number() == 0; + case internal::WireFormatLite::CPPTYPE_INT32: + return field->default_value_int32() == 0; + case internal::WireFormatLite::CPPTYPE_INT64: + return field->default_value_int64() == 0; + case internal::WireFormatLite::CPPTYPE_UINT32: + return field->default_value_uint32() == 0; + case internal::WireFormatLite::CPPTYPE_UINT64: + return field->default_value_uint64() == 0; + case internal::WireFormatLite::CPPTYPE_FLOAT: + return field->default_value_float() == 0; + case internal::WireFormatLite::CPPTYPE_DOUBLE: + return field->default_value_double() == 0; + case internal::WireFormatLite::CPPTYPE_BOOL: + return field->default_value_bool() == false; + default: + return false; + } } void MessageGenerator:: @@ -303,10 +528,11 @@ GenerateClassDefinition(io::Printer* printer) { map vars; vars["classname"] = classname_; vars["field_count"] = SimpleItoa(descriptor_->field_count()); - if (dllexport_decl_.empty()) { + vars["oneof_decl_count"] = SimpleItoa(descriptor_->oneof_decl_count()); + if (options_.dllexport_decl.empty()) { vars["dllexport"] = ""; } else { - vars["dllexport"] = dllexport_decl_ + " "; + vars["dllexport"] = options_.dllexport_decl + " "; } vars["superclass"] = SuperClassName(descriptor_); @@ -327,7 +553,7 @@ GenerateClassDefinition(io::Printer* printer) { "}\n" "\n"); - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print( "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n" " return _unknown_fields_;\n" @@ -337,6 +563,16 @@ GenerateClassDefinition(io::Printer* printer) { " return &_unknown_fields_;\n" "}\n" "\n"); + } else { + printer->Print( + "inline const ::std::string& unknown_fields() const {\n" + " return _unknown_fields_;\n" + "}\n" + "\n" + "inline ::std::string* mutable_unknown_fields() {\n" + " return &_unknown_fields_;\n" + "}\n" + "\n"); } // Only generate this member if it's not disabled. @@ -350,6 +586,47 @@ GenerateClassDefinition(io::Printer* printer) { "static const $classname$& default_instance();\n" "\n"); + // Generate enum values for every field in oneofs. One list is generated for + // each oneof with an additional *_NOT_SET value. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "enum $camel_oneof_name$Case {\n", + "camel_oneof_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + printer->Print( + "k$field_name$ = $field_number$,\n", + "field_name", + UnderscoresToCamelCase( + descriptor_->oneof_decl(i)->field(j)->name(), true), + "field_number", + SimpleItoa(descriptor_->oneof_decl(i)->field(j)->number())); + } + printer->Print( + "$cap_oneof_name$_NOT_SET = 0,\n", + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "};\n" + "\n"); + } + + if (!StaticInitializersForced(descriptor_->file())) { + printer->Print(vars, + "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" + "// Returns the internal default instance pointer. This function can\n" + "// return NULL thus should not be used by the user. This is intended\n" + "// for Protobuf internal code. Please use default_instance() declared\n" + "// above instead.\n" + "static inline const $classname$* internal_default_instance() {\n" + " return default_instance_;\n" + "}\n" + "#endif\n" + "\n"); + } + printer->Print(vars, "void Swap($classname$* other);\n" @@ -379,20 +656,50 @@ GenerateClassDefinition(io::Printer* printer) { " ::google::protobuf::io::CodedInputStream* input);\n" "void SerializeWithCachedSizes(\n" " ::google::protobuf::io::CodedOutputStream* output) const;\n"); + // DiscardUnknownFields() is implemented in message.cc using reflections. We + // need to implement this function in generated code for messages. + if (!UseUnknownFieldSet(descriptor_->file())) { + printer->Print( + "void DiscardUnknownFields();\n"); + } if (HasFastArraySerialization(descriptor_->file())) { printer->Print( "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n"); } } - printer->Print(vars, + // Check all FieldDescriptors including those in oneofs to estimate + // whether ::std::string is likely to be used, and depending on that + // estimate, set uses_string_ to true or false. That contols + // whether to force initialization of empty_string_ in SharedCtor(). + // It's often advantageous to do so to keep "is empty_string_ + // inited?" code from appearing all over the place. + vector descriptors; + for (int i = 0; i < descriptor_->field_count(); i++) { + descriptors.push_back(descriptor_->field(i)); + } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + descriptors.push_back(descriptor_->oneof_decl(i)->field(j)); + } + } + uses_string_ = false; + for (int i = 0; i < descriptors.size(); i++) { + const FieldDescriptor* field = descriptors[i]; + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + switch (field->options().ctype()) { + default: uses_string_ = true; break; + } + } + } + + printer->Print( "int GetCachedSize() const { return _cached_size_; }\n" "private:\n" "void SharedCtor();\n" "void SharedDtor();\n" "void SetCachedSize(int size) const;\n" - "public:\n" - "\n"); + "public:\n"); if (HasDescriptorMethods(descriptor_->file())) { printer->Print( @@ -444,38 +751,172 @@ GenerateClassDefinition(io::Printer* printer) { "// @@protoc_insertion_point(class_scope:$full_name$)\n", "full_name", descriptor_->full_name()); - // Generate private members for fields. + // Generate private members. printer->Outdent(); printer->Print(" private:\n"); printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->is_repeated()) { + printer->Print( + "inline void set_has_$name$();\n", + "name", FieldName(descriptor_->field(i))); + if (!descriptor_->field(i)->containing_oneof()) { + printer->Print( + "inline void clear_has_$name$();\n", + "name", FieldName(descriptor_->field(i))); + } + } + } + printer->Print("\n"); + + // Generate oneof function declarations + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "inline bool has_$oneof_name$();\n" + "void clear_$oneof_name$();\n" + "inline void clear_has_$oneof_name$();\n\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } + + // Prepare decls for _cached_size_ and _has_bits_. Their position in the + // output will be determined later. + + bool need_to_emit_cached_size = true; + // TODO(kenton): Make _cached_size_ an atomic when C++ supports it. + const string cached_size_decl = "mutable int _cached_size_;\n"; + + // TODO(jieluo) - Optimize _has_bits_ for repeated and oneof fields. + size_t sizeof_has_bits = (descriptor_->field_count() + 31) / 32 * 4; + if (descriptor_->field_count() == 0) { + // Zero-size arrays aren't technically allowed, and MSVC in particular + // doesn't like them. We still need to declare these arrays to make + // other code compile. Since this is an uncommon case, we'll just declare + // them with size 1 and waste some space. Oh well. + sizeof_has_bits = 4; + } + const string has_bits_decl = sizeof_has_bits == 0 ? "" : + "::google::protobuf::uint32 _has_bits_[" + SimpleItoa(sizeof_has_bits / 4) + "];\n"; + + + // To minimize padding, data members are divided into three sections: + // (1) members assumed to align to 8 bytes + // (2) members corresponding to message fields, re-ordered to optimize + // alignment. + // (3) members assumed to align to 4 bytes. + + // Members assumed to align to 8 bytes: + if (descriptor_->extension_range_count() > 0) { printer->Print( - "::google::protobuf::internal::ExtensionSet _extensions_;\n"); + "::google::protobuf::internal::ExtensionSet _extensions_;\n" + "\n"); } - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print( - "::google::protobuf::UnknownFieldSet _unknown_fields_;\n"); + "::google::protobuf::UnknownFieldSet _unknown_fields_;\n" + "\n"); + } else { + printer->Print( + "::std::string _unknown_fields_;\n" + "\n"); } - // TODO(kenton): Make _cached_size_ an atomic when C++ supports it. - printer->Print( - "mutable int _cached_size_;\n" - "\n"); + // _has_bits_ is frequently accessed, so to reduce code size and improve + // speed, it should be close to the start of the object. But, try not to + // waste space:_has_bits_ by itself always makes sense if its size is a + // multiple of 8, but, otherwise, maybe _has_bits_ and cached_size_ together + // will work well. + printer->Print(has_bits_decl.c_str()); + if ((sizeof_has_bits % 8) != 0) { + printer->Print(cached_size_decl.c_str()); + need_to_emit_cached_size = false; + } + + // Field members: + + // List fields which doesn't belong to any oneof + vector fields; + hash_map fieldname_to_chunk; for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GeneratePrivateMembers(printer); + if (!descriptor_->field(i)->containing_oneof()) { + const FieldDescriptor* field = descriptor_->field(i); + fields.push_back(field); + fieldname_to_chunk[FieldName(field)] = i / 8; + } + } + OptimizePadding(&fields); + // Emit some private and static members + runs_of_fields_ = vector< vector >(1); + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + const FieldGenerator& generator = field_generators_.get(field); + generator.GenerateStaticMembers(printer); + generator.GeneratePrivateMembers(printer); + if (CanClearByZeroing(field)) { + const string& fieldname = FieldName(field); + if (!runs_of_fields_.back().empty() && + (fieldname_to_chunk[runs_of_fields_.back().back()] != + fieldname_to_chunk[fieldname])) { + runs_of_fields_.push_back(vector()); + } + runs_of_fields_.back().push_back(fieldname); + } else if (!runs_of_fields_.back().empty()) { + runs_of_fields_.push_back(vector()); + } + } + + // For each oneof generate a union + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "union $camel_oneof_name$Union {\n", + "camel_oneof_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + field_generators_.get(descriptor_->oneof_decl(i)-> + field(j)).GeneratePrivateMembers(printer); + } + printer->Outdent(); + printer->Print( + "} $oneof_name$_;\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + field_generators_.get(descriptor_->oneof_decl(i)-> + field(j)).GenerateStaticMembers(printer); + } + } + + // Members assumed to align to 4 bytes: + + if (need_to_emit_cached_size) { + printer->Print(cached_size_decl.c_str()); + need_to_emit_cached_size = false; + } + + // Generate _oneof_case_. + if (descriptor_->oneof_decl_count() > 0) { + printer->Print(vars, + "::google::protobuf::uint32 _oneof_case_[$oneof_decl_count$];\n" + "\n"); } // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as // friends so that they can access private static variables like // default_instance_ and reflection_. - printer->Print( + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. "friend void $dllexport_decl$ $adddescriptorsname$();\n", - "dllexport_decl", dllexport_decl_, + // Without. + "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n", + // Vars. + "dllexport_decl", options_.dllexport_decl, "adddescriptorsname", - GlobalAddDescriptorsName(descriptor_->file()->name())); + GlobalAddDescriptorsName(descriptor_->file()->name())); + printer->Print( "friend void $assigndescriptorsname$();\n" "friend void $shutdownfilename$();\n" @@ -484,38 +925,14 @@ GenerateClassDefinition(io::Printer* printer) { GlobalAssignDescriptorsName(descriptor_->file()->name()), "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name())); - // Generate offsets and _has_bits_ boilerplate. - if (descriptor_->field_count() > 0) { - printer->Print(vars, - "::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n"); - } else { - // Zero-size arrays aren't technically allowed, and MSVC in particular - // doesn't like them. We still need to declare these arrays to make - // other code compile. Since this is an uncommon case, we'll just declare - // them with size 1 and waste some space. Oh well. - printer->Print( - "::google::protobuf::uint32 _has_bits_[1];\n"); - } - printer->Print( - "\n" - "// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?\n" - "inline bool _has_bit(int index) const {\n" - " return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;\n" - "}\n" - "inline void _set_bit(int index) {\n" - " _has_bits_[index / 32] |= (1u << (index % 32));\n" - "}\n" - "inline void _clear_bit(int index) {\n" - " _has_bits_[index / 32] &= ~(1u << (index % 32));\n" - "}\n" - "\n" "void InitAsDefaultInstance();\n" "static $classname$* default_instance_;\n", "classname", classname_); printer->Outdent(); printer->Print(vars, "};"); + GOOGLE_DCHECK(!need_to_emit_cached_size); } void MessageGenerator:: @@ -527,6 +944,23 @@ GenerateInlineMethods(io::Printer* printer) { } GenerateFieldAccessorDefinitions(printer); + + // Generate oneof_case() functions. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + map vars; + vars["class_name"] = classname_; + vars["camel_oneof_name"] = UnderscoresToCamelCase( + descriptor_->oneof_decl(i)->name(), true); + vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + printer->Print( + vars, + "inline $class_name$::$camel_oneof_name$Case $class_name$::" + "$oneof_name$_case() const {\n" + " return $class_name$::$camel_oneof_name$Case(" + "_oneof_case_[$oneof_index$]);\n" + "}\n"); + } } void MessageGenerator:: @@ -537,6 +971,25 @@ GenerateDescriptorDeclarations(io::Printer* printer) { " $name$_reflection_ = NULL;\n", "name", classname_); + // Generate oneof default instance for reflection usage. + if (descriptor_->oneof_decl_count() > 0) { + printer->Print("struct $name$OneofInstance {\n", + "name", classname_); + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print(" "); + if (IsStringOrMessage(field)) { + printer->Print("const "); + } + field_generators_.get(field).GeneratePrivateMembers(printer); + } + } + + printer->Print("}* $name$_default_oneof_instance_ = NULL;\n", + "name", classname_); + } + for (int i = 0; i < descriptor_->nested_type_count(); i++) { nested_generators_[i]->GenerateDescriptorDeclarations(printer); } @@ -589,9 +1042,19 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) { printer->Print(vars, " -1,\n"); } + + if (descriptor_->oneof_decl_count() > 0) { + printer->Print(vars, + " $classname$_default_oneof_instance_,\n" + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" + "$classname$, _oneof_case_[0]),\n"); + } + + printer->Print( + " ::google::protobuf::DescriptorPool::generated_pool(),\n"); + printer->Print(vars, + " ::google::protobuf::MessageFactory::generated_factory(),\n"); printer->Print(vars, - " ::google::protobuf::DescriptorPool::generated_pool(),\n" - " ::google::protobuf::MessageFactory::generated_factory(),\n" " sizeof($classname$));\n"); // Handle nested types. @@ -620,6 +1083,13 @@ GenerateTypeRegistrations(io::Printer* printer) { void MessageGenerator:: GenerateDefaultInstanceAllocator(io::Printer* printer) { + // Construct the default instances of all fields, as they will be used + // when creating the default instance of the entire message. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateDefaultInstanceAllocator(printer); + } + // Construct the default instance. We can't call InitAsDefaultInstance() yet // because we need to make sure all default instances that this one might // depend on are constructed first. @@ -627,6 +1097,13 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) { "$classname$::default_instance_ = new $classname$();\n", "classname", classname_); + if ((descriptor_->oneof_decl_count() > 0) && + HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "$classname$_default_oneof_instance_ = new $classname$OneofInstance;\n", + "classname", classname_); + } + // Handle nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { nested_generators_[i]->GenerateDefaultInstanceAllocator(printer); @@ -658,11 +1135,22 @@ GenerateShutdownCode(io::Printer* printer) { "classname", classname_); if (HasDescriptorMethods(descriptor_->file())) { + if (descriptor_->oneof_decl_count() > 0) { + printer->Print( + "delete $classname$_default_oneof_instance_;\n", + "classname", classname_); + } printer->Print( "delete $classname$_reflection_;\n", "classname", classname_); } + // Handle default instances of fields. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateShutdownCode(printer); + } + // Handle nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { nested_generators_[i]->GenerateShutdownCode(printer); @@ -709,6 +1197,11 @@ GenerateClassMethods(io::Printer* printer) { GenerateStructors(printer); printer->Print("\n"); + if (descriptor_->oneof_decl_count() > 0) { + GenerateOneofClear(printer); + printer->Print("\n"); + } + if (HasGeneratedMethods(descriptor_->file())) { GenerateClear(printer); printer->Print("\n"); @@ -768,15 +1261,33 @@ GenerateOffsets(io::Printer* printer) { printer->Print( "static const int $classname$_offsets_[$field_count$] = {\n", "classname", classname_, - "field_count", SimpleItoa(max(1, descriptor_->field_count()))); + "field_count", SimpleItoa(max( + 1, descriptor_->field_count() + descriptor_->oneof_decl_count()))); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); + if (field->containing_oneof()) { + printer->Print( + "PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(" + "$classname$_default_oneof_instance_, $name$_),\n", + "classname", classname_, + "name", FieldName(field)); + } else { + printer->Print( + "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " + "$name$_),\n", + "classname", classname_, + "name", FieldName(field)); + } + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); printer->Print( "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n", "classname", classname_, - "name", FieldName(field)); + "name", oneof->name()); } printer->Outdent(); @@ -790,17 +1301,26 @@ GenerateSharedConstructorCode(io::Printer* printer) { "classname", classname_); printer->Indent(); - printer->Print( - "_cached_size_ = 0;\n"); + printer->Print(StrCat( + uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "", + "_cached_size_ = 0;\n").c_str()); for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateConstructorCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateConstructorCode(printer); + } } printer->Print( "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "clear_has_$oneof_name$();\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } + printer->Outdent(); printer->Print("}\n\n"); } @@ -811,14 +1331,29 @@ GenerateSharedDestructorCode(io::Printer* printer) { "void $classname$::SharedDtor() {\n", "classname", classname_); printer->Indent(); - // Write the destructors for each field. + // Write the destructors for each field except oneof members. for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateDestructorCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateDestructorCode(printer); + } } - printer->Print( - "if (this != default_instance_) {\n"); + // Generate code to destruct oneofs. Clearing should do the work. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "if (has_$oneof_name$()) {\n" + " clear_$oneof_name$();\n" + "}\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } + + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. + "if (this != default_instance_) {\n", + // Without. + "if (this != &default_instance()) {\n"); // We need to delete all embedded messages. // TODO(kenton): If we make unset messages point at default instances @@ -829,8 +1364,12 @@ GenerateSharedDestructorCode(io::Printer* printer) { if (!field->is_repeated() && field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - printer->Print(" delete $name$_;\n", - "name", FieldName(field)); + // Skip oneof members + if (!field->containing_oneof()) { + printer->Print( + " delete $name$_;\n", + "name", FieldName(field)); + } } } @@ -850,9 +1389,11 @@ GenerateStructors(io::Printer* printer) { "$classname$::$classname$()\n" " : $superclass$() {\n" " SharedCtor();\n" + " // @@protoc_insertion_point(constructor:$full_name$)\n" "}\n", "classname", classname_, - "superclass", superclass); + "superclass", superclass, + "full_name", descriptor_->full_name()); printer->Print( "\n" @@ -869,11 +1410,28 @@ GenerateStructors(io::Printer* printer) { const FieldDescriptor* field = descriptor_->field(i); if (!field->is_repeated() && - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - printer->Print( - " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n", - "name", FieldName(field), - "type", FieldMessageTypeName(field)); + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + (field->containing_oneof() == NULL || + HasDescriptorMethods(descriptor_->file()))) { + string name; + if (field->containing_oneof()) { + name = classname_ + "_default_oneof_instance_->"; + } + name += FieldName(field); + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. + " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n", + // Without. + " $name$_ = const_cast< $type$*>(\n" + " $type$::internal_default_instance());\n", + // Vars. + "name", name, + "type", FieldMessageTypeName(field)); + } else if (field->containing_oneof() && + HasDescriptorMethods(descriptor_->file())) { + field_generators_.get(descriptor_->field(i)) + .GenerateConstructorCode(printer); } } printer->Print( @@ -886,10 +1444,12 @@ GenerateStructors(io::Printer* printer) { " : $superclass$() {\n" " SharedCtor();\n" " MergeFrom(from);\n" + " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" "}\n" "\n", "classname", classname_, - "superclass", superclass); + "superclass", superclass, + "full_name", descriptor_->full_name()); // Generate the shared constructor code. GenerateSharedConstructorCode(printer); @@ -897,10 +1457,12 @@ GenerateStructors(io::Printer* printer) { // Generate the destructor. printer->Print( "$classname$::~$classname$() {\n" + " // @@protoc_insertion_point(destructor:$full_name$)\n" " SharedDtor();\n" "}\n" "\n", - "classname", classname_); + "classname", classname_, + "full_name", descriptor_->full_name()); // Generate the shared destructor code. GenerateSharedDestructorCode(printer); @@ -929,86 +1491,178 @@ GenerateStructors(io::Printer* printer) { } printer->Print( - "const $classname$& $classname$::default_instance() {\n" - " if (default_instance_ == NULL) $adddescriptorsname$();" + "const $classname$& $classname$::default_instance() {\n", + "classname", classname_); + + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. + " if (default_instance_ == NULL) $adddescriptorsname$();\n", + // Without. + " $adddescriptorsname$();\n", + // Vars. + "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); + + printer->Print( " return *default_instance_;\n" "}\n" "\n" "$classname$* $classname$::default_instance_ = NULL;\n" - "\n" + "\n", + "classname", classname_); + + printer->Print( "$classname$* $classname$::New() const {\n" " return new $classname$;\n" "}\n", - "classname", classname_, - "adddescriptorsname", - GlobalAddDescriptorsName(descriptor_->file()->name())); + "classname", classname_); } +// Return the number of bits set in n, a non-negative integer. +static int popcnt(uint32 n) { + int result = 0; + while (n != 0) { + result += (n & 1); + n = n / 2; + } + return result; +} + void MessageGenerator:: GenerateClear(io::Printer* printer) { printer->Print("void $classname$::Clear() {\n", "classname", classname_); printer->Indent(); - int last_index = -1; - + // Step 1: Extensions if (descriptor_->extension_range_count() > 0) { printer->Print("_extensions_.Clear();\n"); } + // Step 2: Everything but extensions, repeateds, unions. + // These are handled in chunks of 8. The first chunk is + // the non-extensions-non-repeateds-non-unions in + // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7), + // and the second chunk is the same for + // descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15), + // etc. + set step2_indices; + hash_map fieldname_to_chunk; + hash_map memsets_for_chunk; + hash_map memset_field_count_for_chunk; + hash_set handled; // fields that appear anywhere in memsets_for_chunk + hash_map fields_mask_for_chunk; for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); + if (!field->is_repeated() && !field->containing_oneof()) { + step2_indices.insert(i); + int chunk = i / 8; + fieldname_to_chunk[FieldName(field)] = chunk; + fields_mask_for_chunk[chunk] |= static_cast(1) << (i % 32); + } + } - if (!field->is_repeated()) { - map vars; - vars["index"] = SimpleItoa(field->index()); - - // We can use the fact that _has_bits_ is a giant bitfield to our - // advantage: We can check up to 32 bits at a time for equality to - // zero, and skip the whole range if so. This can improve the speed - // of Clear() for messages which contain a very large number of - // optional fields of which only a few are used at a time. Here, - // we've chosen to check 8 bits at a time rather than 32. - if (i / 8 != last_index / 8 || last_index < 0) { - if (last_index >= 0) { - printer->Outdent(); - printer->Print("}\n"); - } - printer->Print(vars, - "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n"); - printer->Indent(); + // Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0. + // The generated code uses two macros to help it clear runs of fields: + // OFFSET_OF_FIELD_ computes the offset (in bytes) of a field in the Message. + // ZR_ zeroes a non-empty range of fields via memset. + const char* macros = + "#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \\\n" + " &reinterpret_cast<$classname$*>(16)->f) - \\\n" + " reinterpret_cast(16))\n\n" + "#define ZR_(first, last) do { \\\n" + " size_t f = OFFSET_OF_FIELD_(first); \\\n" + " size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \\\n" + " ::memset(&first, 0, n); \\\n" + " } while (0)\n\n"; + for (int i = 0; i < runs_of_fields_.size(); i++) { + const vector& run = runs_of_fields_[i]; + if (run.size() < 2) continue; + const string& first_field_name = run[0]; + const string& last_field_name = run.back(); + int chunk = fieldname_to_chunk[run[0]]; + memsets_for_chunk[chunk].append( + "ZR_(" + first_field_name + "_, " + last_field_name + "_);\n"); + for (int j = 0; j < run.size(); j++) { + GOOGLE_DCHECK_EQ(chunk, fieldname_to_chunk[run[j]]); + handled.insert(run[j]); + } + memset_field_count_for_chunk[chunk] += run.size(); + } + const bool macros_are_needed = handled.size() > 0; + if (macros_are_needed) { + printer->Outdent(); + printer->Print(macros, + "classname", classname_); + printer->Indent(); + } + // Step 2b: Finish step 2, ignoring fields handled in step 2a. + int last_index = -1; + bool chunk_block_in_progress = false; + for (int i = 0; i < descriptor_->field_count(); i++) { + if (step2_indices.count(i) == 0) continue; + const FieldDescriptor* field = descriptor_->field(i); + const string fieldname = FieldName(field); + if (i / 8 != last_index / 8 || last_index < 0) { + // End previous chunk, if there was one. + if (chunk_block_in_progress) { + printer->Outdent(); + printer->Print("}\n"); + chunk_block_in_progress = false; } - last_index = i; - - // It's faster to just overwrite primitive types, but we should - // only clear strings and messages if they were set. - // TODO(kenton): Let the CppFieldGenerator decide this somehow. - bool should_check_bit = - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || - field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; - - if (should_check_bit) { - printer->Print(vars, "if (_has_bit($index$)) {\n"); + // Start chunk. + const string& memsets = memsets_for_chunk[i / 8]; + uint32 mask = fields_mask_for_chunk[i / 8]; + int count = popcnt(mask); + if (count == 1 || + (count <= 4 && count == memset_field_count_for_chunk[i / 8])) { + // No "if" here because the chunk is trivial. + } else { + printer->Print( + "if (_has_bits_[$index$ / 32] & $mask$) {\n", + "index", SimpleItoa(i / 8 * 8), + "mask", SimpleItoa(mask)); printer->Indent(); + chunk_block_in_progress = true; } + printer->Print(memsets.c_str()); + } + last_index = i; + if (handled.count(fieldname) > 0) continue; + + // It's faster to just overwrite primitive types, but we should + // only clear strings and messages if they were set. + // TODO(kenton): Let the CppFieldGenerator decide this somehow. + bool should_check_bit = + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || + field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; + + if (should_check_bit) { + printer->Print("if (has_$name$()) {\n", "name", fieldname); + printer->Indent(); + } - field_generators_.get(field).GenerateClearingCode(printer); + field_generators_.get(field).GenerateClearingCode(printer); - if (should_check_bit) { - printer->Outdent(); - printer->Print("}\n"); - } + if (should_check_bit) { + printer->Outdent(); + printer->Print("}\n"); } } - if (last_index >= 0) { + if (chunk_block_in_progress) { printer->Outdent(); printer->Print("}\n"); } + if (macros_are_needed) { + printer->Outdent(); + printer->Print("\n#undef OFFSET_OF_FIELD_\n#undef ZR_\n\n"); + printer->Indent(); + } - // Repeated fields don't use _has_bits_ so we clear them in a separate - // pass. + // Step 3: Repeated fields don't use _has_bits_; emit code to clear them here. for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); @@ -1017,12 +1671,23 @@ GenerateClear(io::Printer* printer) { } } + // Step 4: Unions. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "clear_$oneof_name$();\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } + + // Step 5: Everything else. printer->Print( "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print( "mutable_unknown_fields()->Clear();\n"); + } else { + printer->Print( + "mutable_unknown_fields()->clear();\n"); } printer->Outdent(); @@ -1030,6 +1695,58 @@ GenerateClear(io::Printer* printer) { } void MessageGenerator:: +GenerateOneofClear(io::Printer* printer) { + // Generated function clears the active field and union case (e.g. foo_case_). + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "void $classname$::clear_$oneofname$() {\n", + "classname", classname_, + "oneofname", descriptor_->oneof_decl(i)->name()); + printer->Indent(); + printer->Print( + "switch($oneofname$_case()) {\n", + "oneofname", descriptor_->oneof_decl(i)->name()); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "case k$field_name$: {\n", + "field_name", UnderscoresToCamelCase(field->name(), true)); + printer->Indent(); + // We clear only allocated objects in oneofs + if (!IsStringOrMessage(field)) { + printer->Print( + "// No need to clear\n"); + } else { + field_generators_.get(field).GenerateClearingCode(printer); + } + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "}\n" + "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n", + "oneof_index", SimpleItoa(i), + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + } +} + +void MessageGenerator:: GenerateSwap(io::Printer* printer) { // Generate the Swap member function. printer->Print("void $classname$::Swap($classname$* other) {\n", @@ -1044,13 +1761,23 @@ GenerateSwap(io::Printer* printer) { field_generators_.get(field).GenerateSwappingCode(printer); } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "std::swap($oneof_name$_, other->$oneof_name$_);\n" + "std::swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n", + "oneof_name", descriptor_->oneof_decl(i)->name(), + "i", SimpleItoa(i)); + } + for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) { printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n", "i", SimpleItoa(i)); } - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); + } else { + printer->Print("_unknown_fields_.swap(other->_unknown_fields_);\n"); } printer->Print("std::swap(_cached_size_, other->_cached_size_);\n"); if (descriptor_->extension_range_count() > 0) { @@ -1122,31 +1849,60 @@ GenerateMergeFrom(io::Printer* printer) { } } + // Merge oneof fields. Oneof field requires oneof case check. + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + printer->Print( + "switch (from.$oneofname$_case()) {\n", + "oneofname", descriptor_->oneof_decl(i)->name()); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "case k$field_name$: {\n", + "field_name", UnderscoresToCamelCase(field->name(), true)); + printer->Indent(); + field_generators_.get(field).GenerateMergingCode(printer); + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "}\n"); + } + // Merge Optional and Required fields (after a _has_bit check). int last_index = -1; for (int i = 0; i < descriptor_->field_count(); ++i) { const FieldDescriptor* field = descriptor_->field(i); - if (!field->is_repeated()) { - map vars; - vars["index"] = SimpleItoa(field->index()); - + if (!field->is_repeated() && !field->containing_oneof()) { // See above in GenerateClear for an explanation of this. if (i / 8 != last_index / 8 || last_index < 0) { if (last_index >= 0) { printer->Outdent(); printer->Print("}\n"); } - printer->Print(vars, - "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n"); + printer->Print( + "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n", + "index", SimpleItoa(field->index())); printer->Indent(); } last_index = i; - printer->Print(vars, - "if (from._has_bit($index$)) {\n"); + printer->Print( + "if (from.has_$name$()) {\n", + "name", FieldName(field)); printer->Indent(); field_generators_.get(field).GenerateMergingCode(printer); @@ -1165,9 +1921,12 @@ GenerateMergeFrom(io::Printer* printer) { printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); } - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print( "mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"); + } else { + printer->Print( + "mutable_unknown_fields()->append(from.unknown_fields());\n"); } printer->Outdent(); @@ -1214,25 +1973,61 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // Special-case MessageSet. printer->Print( "bool $classname$::MergePartialFromCodedStream(\n" - " ::google::protobuf::io::CodedInputStream* input) {\n" + " ::google::protobuf::io::CodedInputStream* input) {\n", + "classname", classname_); + + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. " return _extensions_.ParseMessageSet(input, default_instance_,\n" - " mutable_unknown_fields());\n" - "}\n", + " mutable_unknown_fields());\n", + // Without. + " return _extensions_.ParseMessageSet(input, &default_instance(),\n" + " mutable_unknown_fields());\n", + // Vars. "classname", classname_); + + printer->Print( + "}\n"); return; } printer->Print( "bool $classname$::MergePartialFromCodedStream(\n" " ::google::protobuf::io::CodedInputStream* input) {\n" - "#define DO_(EXPRESSION) if (!(EXPRESSION)) return false\n" - " ::google::protobuf::uint32 tag;\n" - " while ((tag = input->ReadTag()) != 0) {\n", + "#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure\n" + " ::google::protobuf::uint32 tag;\n", "classname", classname_); + if (!UseUnknownFieldSet(descriptor_->file())) { + printer->Print( + " ::google::protobuf::io::StringOutputStream unknown_fields_string(\n" + " mutable_unknown_fields());\n" + " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" + " &unknown_fields_string);\n"); + } + + printer->Print( + " // @@protoc_insertion_point(parse_start:$full_name$)\n", + "full_name", descriptor_->full_name()); + printer->Indent(); + printer->Print("for (;;) {\n"); printer->Indent(); + scoped_array ordered_fields( + SortFieldsByNumber(descriptor_)); + uint32 maxtag = descriptor_->field_count() == 0 ? 0 : + WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]); + const int kCutoff0 = 127; // fits in 1-byte varint + const int kCutoff1 = (127 << 7) + 127; // fits in 2-byte varint + printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = " + "input->ReadTagWithCutoff($max$);\n" + "tag = p.first;\n" + "if (!p.second) goto handle_unusual;\n", + "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 : + (maxtag <= kCutoff1 ? kCutoff1 : + maxtag))); if (descriptor_->field_count() > 0) { // We don't even want to print the switch() if we have no fields because // MSVC dislikes switch() statements that contain only a default value. @@ -1242,14 +2037,11 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // of each case. However, this is actually a bit slower in practice as it // creates a jump table that is 8x larger and sparser, and meanwhile the // if()s are highly predictable. - printer->Print( - "switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {\n"); + printer->Print("switch (::google::protobuf::internal::WireFormatLite::" + "GetTagFieldNumber(tag)) {\n"); printer->Indent(); - scoped_array ordered_fields( - SortFieldsByNumber(descriptor_)); - for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = ordered_fields[i]; @@ -1262,10 +2054,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) { const FieldGenerator& field_generator = field_generators_.get(field); // Emit code to parse the common, expected case. - printer->Print( - "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" - " ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n", - "wiretype", kWireTypeNames[WireFormat::WireTypeForField(field)]); + printer->Print("if (tag == $commontag$) {\n", + "commontag", SimpleItoa(WireFormat::MakeTag(field))); if (i > 0 || (field->is_repeated() && !field->options().packed())) { printer->Print( @@ -1283,20 +2073,22 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // Emit code to parse unexpectedly packed or unpacked values. if (field->is_packable() && field->options().packed()) { - printer->Print( - "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n" - " == ::google::protobuf::internal::WireFormatLite::\n" - " WIRETYPE_$wiretype$) {\n", - "wiretype", - kWireTypeNames[WireFormat::WireTypeForFieldType(field->type())]); + internal::WireFormatLite::WireType wiretype = + WireFormat::WireTypeForFieldType(field->type()); + printer->Print("} else if (tag == $uncommontag$) {\n", + "uncommontag", SimpleItoa( + internal::WireFormatLite::MakeTag( + field->number(), wiretype))); printer->Indent(); field_generator.GenerateMergeFromCodedStream(printer); printer->Outdent(); } else if (field->is_packable() && !field->options().packed()) { - printer->Print( - "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n" - " == ::google::protobuf::internal::WireFormatLite::\n" - " WIRETYPE_LENGTH_DELIMITED) {\n"); + internal::WireFormatLite::WireType wiretype = + internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED; + printer->Print("} else if (tag == $uncommontag$) {\n", + "uncommontag", SimpleItoa( + internal::WireFormatLite::MakeTag( + field->number(), wiretype))); printer->Indent(); field_generator.GenerateMergeFromCodedStreamWithPacking(printer); printer->Outdent(); @@ -1304,7 +2096,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Print( "} else {\n" - " goto handle_uninterpreted;\n" + " goto handle_unusual;\n" "}\n"); // switch() is slow since it can't be predicted well. Insert some if()s @@ -1328,7 +2120,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // Expect EOF. // TODO(kenton): Expect group end-tag? printer->Print( - "if (input->ExpectAtEnd()) return true;\n"); + "if (input->ExpectAtEnd()) goto success;\n"); } printer->Print( @@ -1338,17 +2130,19 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Print("}\n\n"); } - printer->Print( - "default: {\n" - "handle_uninterpreted:\n"); + printer->Print("default: {\n"); printer->Indent(); } - // Is this an end-group tag? If so, this must be the end of the message. + printer->Outdent(); + printer->Print("handle_unusual:\n"); + printer->Indent(); + // If tag is 0 or an end-group tag then this must be the end of the message. printer->Print( - "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" + "if (tag == 0 ||\n" + " ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" " ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n" - " return true;\n" + " goto success;\n" "}\n"); // Handle extension ranges. @@ -1377,13 +2171,24 @@ GenerateMergeFromCodedStream(io::Printer* printer) { } } printer->Print(") {\n"); - if (HasUnknownFields(descriptor_->file())) { - printer->Print( + if (UseUnknownFieldSet(descriptor_->file())) { + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" + " mutable_unknown_fields()));\n", + // Without. + " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" " mutable_unknown_fields()));\n"); } else { - printer->Print( - " DO_(_extensions_.ParseField(tag, input, default_instance_));\n"); + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. + " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" + " &unknown_fields_stream));\n", + // Without. + " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" + " &unknown_fields_stream));\n"); } printer->Print( " continue;\n" @@ -1391,13 +2196,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) { } // We really don't recognize this tag. Skip it. - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print( "DO_(::google::protobuf::internal::WireFormat::SkipField(\n" " input, tag, mutable_unknown_fields()));\n"); } else { printer->Print( - "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n"); + "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n" + " input, tag, &unknown_fields_stream));\n"); } if (descriptor_->field_count() > 0) { @@ -1411,10 +2217,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Outdent(); printer->Outdent(); printer->Print( - " }\n" // while + " }\n" // for (;;) + "success:\n" + " // @@protoc_insertion_point(parse_success:$full_name$)\n" " return true;\n" + "failure:\n" + " // @@protoc_insertion_point(parse_failure:$full_name$)\n" + " return false;\n" "#undef DO_\n" - "}\n"); + "}\n", "full_name", descriptor_->full_name()); } void MessageGenerator::GenerateSerializeOneField( @@ -1423,8 +2234,8 @@ void MessageGenerator::GenerateSerializeOneField( if (!field->is_repeated()) { printer->Print( - "if (_has_bit($index$)) {\n", - "index", SimpleItoa(field->index())); + "if (has_$name$()) {\n", + "name", FieldName(field)); printer->Indent(); } @@ -1470,11 +2281,10 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) { " ::google::protobuf::io::CodedOutputStream* output) const {\n" " _extensions_.SerializeMessageSetWithCachedSizes(output);\n", "classname", classname_); - if (HasUnknownFields(descriptor_->file())) { - printer->Print( - " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" - " unknown_fields(), output);\n"); - } + GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file())); + printer->Print( + " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" + " unknown_fields(), output);\n"); printer->Print( "}\n"); return; @@ -1486,8 +2296,16 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) { "classname", classname_); printer->Indent(); + printer->Print( + "// @@protoc_insertion_point(serialize_start:$full_name$)\n", + "full_name", descriptor_->full_name()); + GenerateSerializeWithCachedSizesBody(printer, false); + printer->Print( + "// @@protoc_insertion_point(serialize_end:$full_name$)\n", + "full_name", descriptor_->full_name()); + printer->Outdent(); printer->Print( "}\n"); @@ -1503,12 +2321,11 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { " target =\n" " _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n", "classname", classname_); - if (HasUnknownFields(descriptor_->file())) { - printer->Print( - " target = ::google::protobuf::internal::WireFormat::\n" - " SerializeUnknownMessageSetItemsToArray(\n" - " unknown_fields(), target);\n"); - } + GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file())); + printer->Print( + " target = ::google::protobuf::internal::WireFormat::\n" + " SerializeUnknownMessageSetItemsToArray(\n" + " unknown_fields(), target);\n"); printer->Print( " return target;\n" "}\n"); @@ -1521,8 +2338,16 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { "classname", classname_); printer->Indent(); + printer->Print( + "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n", + "full_name", descriptor_->full_name()); + GenerateSerializeWithCachedSizesBody(printer, true); + printer->Print( + "// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n", + "full_name", descriptor_->full_name()); + printer->Outdent(); printer->Print( " return target;\n" @@ -1532,7 +2357,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { void MessageGenerator:: GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { scoped_array ordered_fields( - SortFieldsByNumber(descriptor_)); + SortFieldsByNumber(descriptor_)); vector sorted_extensions; for (int i = 0; i < descriptor_->extension_range_count(); ++i) { @@ -1561,7 +2386,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { } } - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print("if (!unknown_fields().empty()) {\n"); printer->Indent(); if (to_array) { @@ -1578,6 +2403,10 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { printer->Print( "}\n"); + } else { + printer->Print( + "output->WriteRaw(unknown_fields().data(),\n" + " unknown_fields().size());\n"); } } @@ -1589,11 +2418,10 @@ GenerateByteSize(io::Printer* printer) { "int $classname$::ByteSize() const {\n" " int total_size = _extensions_.MessageSetByteSize();\n", "classname", classname_); - if (HasUnknownFields(descriptor_->file())) { - printer->Print( - " total_size += ::google::protobuf::internal::WireFormat::\n" - " ComputeUnknownMessageSetItemsSize(unknown_fields());\n"); - } + GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file())); + printer->Print( + " total_size += ::google::protobuf::internal::WireFormat::\n" + " ComputeUnknownMessageSetItemsSize(unknown_fields());\n"); printer->Print( " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" " _cached_size_ = total_size;\n" @@ -1616,7 +2444,7 @@ GenerateByteSize(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (!field->is_repeated()) { + if (!field->is_repeated() && !field->containing_oneof()) { // See above in GenerateClear for an explanation of this. // TODO(kenton): Share code? Unclear how to do so without // over-engineering. @@ -1666,13 +2494,45 @@ GenerateByteSize(io::Printer* printer) { } } + // Fields inside a oneof don't use _has_bits_ so we count them in a separate + // pass. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "switch ($oneofname$_case()) {\n", + "oneofname", descriptor_->oneof_decl(i)->name()); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + PrintFieldComment(printer, field); + printer->Print( + "case k$field_name$: {\n", + "field_name", UnderscoresToCamelCase(field->name(), true)); + printer->Indent(); + field_generators_.get(field).GenerateByteSize(printer); + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "}\n"); + } + if (descriptor_->extension_range_count() > 0) { printer->Print( "total_size += _extensions_.ByteSize();\n" "\n"); } - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print("if (!unknown_fields().empty()) {\n"); printer->Indent(); printer->Print( @@ -1681,6 +2541,10 @@ GenerateByteSize(io::Printer* printer) { " unknown_fields());\n"); printer->Outdent(); printer->Print("}\n"); + } else { + printer->Print( + "total_size += unknown_fields().size();\n" + "\n"); } // We update _cached_size_ even though this is a const method. In theory, @@ -1734,19 +2598,30 @@ GenerateIsInitialized(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !ShouldIgnoreRequiredFieldCheck(field) && HasRequiredFields(field->message_type())) { if (field->is_repeated()) { printer->Print( - "for (int i = 0; i < $name$_size(); i++) {\n" - " if (!this->$name$(i).IsInitialized()) return false;\n" - "}\n", + "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))" + " return false;\n", "name", FieldName(field)); } else { - printer->Print( - "if (has_$name$()) {\n" - " if (!this->$name$().IsInitialized()) return false;\n" - "}\n", - "name", FieldName(field)); + if (field->options().weak()) { + // For weak fields, use the data member (google::protobuf::Message*) instead + // of the getter to avoid a link dependency on the weak message type + // which is only forward declared. + printer->Print( + "if (has_$name$()) {\n" + " if (!this->$name$_->IsInitialized()) return false;\n" + "}\n", + "name", FieldName(field)); + } else { + printer->Print( + "if (has_$name$()) {\n" + " if (!this->$name$().IsInitialized()) return false;\n" + "}\n", + "name", FieldName(field)); + } } } } diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index 04778f6..3b4085d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -35,9 +35,11 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ +#include #include -#include +#include #include +#include namespace google { namespace protobuf { @@ -57,7 +59,7 @@ class MessageGenerator { public: // See generator.cc for the meaning of dllexport_decl. explicit MessageGenerator(const Descriptor* descriptor, - const string& dllexport_decl); + const Options& options); ~MessageGenerator(); // Header stuff. @@ -131,6 +133,7 @@ class MessageGenerator { // Generate standard Message methods. void GenerateClear(io::Printer* printer); + void GenerateOneofClear(io::Printer* printer); void GenerateMergeFromCodedStream(io::Printer* printer); void GenerateSerializeWithCachedSizes(io::Printer* printer); void GenerateSerializeWithCachedSizesToArray(io::Printer* printer); @@ -153,11 +156,13 @@ class MessageGenerator { const Descriptor* descriptor_; string classname_; - string dllexport_decl_; + Options options_; FieldGeneratorMap field_generators_; + vector< vector > runs_of_fields_; // that might be trivially cleared scoped_array > nested_generators_; scoped_array > enum_generators_; scoped_array > extension_generators_; + bool uses_string_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index c04bdc6..08a4f25 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -45,13 +45,20 @@ namespace cpp { namespace { void SetMessageVariables(const FieldDescriptor* descriptor, - map* variables) { - SetCommonFieldVariables(descriptor, variables); + map* variables, + const Options& options) { + SetCommonFieldVariables(descriptor, variables, options); (*variables)["type"] = FieldMessageTypeName(descriptor); (*variables)["stream_writer"] = (*variables)["declared_type"] + (HasFastArraySerialization(descriptor->message_type()->file()) ? "MaybeToArray" : ""); + // NOTE: Escaped here to unblock proto1->proto2 migration. + // TODO(liujisi): Extend this to apply for other conflicting methods. + (*variables)["release_name"] = + SafeFunctionName(descriptor->containing_type(), + descriptor, "release_"); + (*variables)["full_name"] = descriptor->full_name(); } } // namespace @@ -59,9 +66,10 @@ void SetMessageVariables(const FieldDescriptor* descriptor, // =================================================================== MessageFieldGenerator:: -MessageFieldGenerator(const FieldDescriptor* descriptor) +MessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) : descriptor_(descriptor) { - SetMessageVariables(descriptor, &variables_); + SetMessageVariables(descriptor, &variables_, options); } MessageFieldGenerator::~MessageFieldGenerator() {} @@ -75,19 +83,47 @@ void MessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, "inline const $type$& $name$() const$deprecation$;\n" - "inline $type$* mutable_$name$()$deprecation$;\n"); + "inline $type$* mutable_$name$()$deprecation$;\n" + "inline $type$* $release_name$()$deprecation$;\n" + "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n"); } void MessageFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline const $type$& $classname$::$name$() const {\n" - " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n"); + + PrintHandlingOptionalStaticInitializers( + variables_, descriptor_->file(), printer, + // With static initializers. + " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n", + // Without. + " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n"); + + printer->Print(variables_, "}\n" "inline $type$* $classname$::mutable_$name$() {\n" - " _set_bit($index$);\n" + " set_has_$name$();\n" " if ($name$_ == NULL) $name$_ = new $type$;\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_;\n" + "}\n" + "inline $type$* $classname$::$release_name$() {\n" + " clear_has_$name$();\n" + " $type$* temp = $name$_;\n" + " $name$_ = NULL;\n" + " return temp;\n" + "}\n" + "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" + " delete $name$_;\n" + " $name$_ = $name$;\n" + " if ($name$) {\n" + " set_has_$name$();\n" + " } else {\n" + " clear_has_$name$();\n" + " }\n" + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); } @@ -151,10 +187,74 @@ GenerateByteSize(io::Printer* printer) const { // =================================================================== +MessageOneofFieldGenerator:: +MessageOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : MessageFieldGenerator(descriptor, options) { + SetCommonOneofFieldVariables(descriptor, &variables_); +} + +MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} + +void MessageOneofFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline const $type$& $classname$::$name$() const {\n" + " return has_$name$() ? *$oneof_prefix$$name$_\n" + " : $type$::default_instance();\n" + "}\n" + "inline $type$* $classname$::mutable_$name$() {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $oneof_prefix$$name$_ = new $type$;\n" + " }\n" + " return $oneof_prefix$$name$_;\n" + "}\n" + "inline $type$* $classname$::$release_name$() {\n" + " if (has_$name$()) {\n" + " clear_has_$oneof_name$();\n" + " $type$* temp = $oneof_prefix$$name$_;\n" + " $oneof_prefix$$name$_ = NULL;\n" + " return temp;\n" + " } else {\n" + " return NULL;\n" + " }\n" + "}\n" + "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" + " clear_$oneof_name$();\n" + " if ($name$) {\n" + " set_has_$name$();\n" + " $oneof_prefix$$name$_ = $name$;\n" + " }\n" + "}\n"); +} + +void MessageOneofFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + // if it is the active field, it cannot be NULL. + printer->Print(variables_, + "delete $oneof_prefix$$name$_;\n"); +} + +void MessageOneofFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + // Don't print any swapping code. Swapping the union will swap this field. +} + +void MessageOneofFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + // Don't print any constructor code. The field is in a union. We allocate + // space only when this field is used. +} + +// =================================================================== + RepeatedMessageFieldGenerator:: -RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor) +RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) : descriptor_(descriptor) { - SetMessageVariables(descriptor, &variables_); + SetMessageVariables(descriptor, &variables_, options); } RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} @@ -182,21 +282,26 @@ void RepeatedMessageFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline const $type$& $classname$::$name$(int index) const {\n" - " return $name$_.Get(index);\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return $name$_.$cppget$(index);\n" "}\n" "inline $type$* $classname$::mutable_$name$(int index) {\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable(index);\n" "}\n" "inline $type$* $classname$::add_$name$() {\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" " return $name$_.Add();\n" "}\n"); printer->Print(variables_, "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h index f514727..4c01795 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h @@ -46,7 +46,8 @@ namespace cpp { class MessageFieldGenerator : public FieldGenerator { public: - explicit MessageFieldGenerator(const FieldDescriptor* descriptor); + explicit MessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~MessageFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -62,16 +63,34 @@ class MessageFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); }; +class MessageOneofFieldGenerator : public MessageFieldGenerator { + public: + explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~MessageOneofFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); +}; + class RepeatedMessageFieldGenerator : public FieldGenerator { public: - explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor); + explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~RepeatedMessageFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h new file mode 100644 index 0000000..7877066 --- /dev/null +++ b/src/google/protobuf/compiler/cpp/cpp_options.h @@ -0,0 +1,58 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: rennie@google.com (Jeffrey Rennie) + +#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ + +#include + +#include +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +// Generator options: +struct Options { + Options() : safe_boundary_check(false) { + } + string dllexport_decl; + bool safe_boundary_check; +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc index 440b716..697b95f 100644 --- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc @@ -34,6 +34,8 @@ // It seemed like parameterizing it would add more complexity than it is // worth. +#include + #include #include #include @@ -56,24 +58,24 @@ class TestGenerator : public CodeGenerator { virtual bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { - TryInsert("test.pb.h", "includes", output_directory); - TryInsert("test.pb.h", "namespace_scope", output_directory); - TryInsert("test.pb.h", "global_scope", output_directory); - TryInsert("test.pb.h", "class_scope:foo.Bar", output_directory); - TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", output_directory); - - TryInsert("test.pb.cc", "includes", output_directory); - TryInsert("test.pb.cc", "namespace_scope", output_directory); - TryInsert("test.pb.cc", "global_scope", output_directory); + TryInsert("test.pb.h", "includes", context); + TryInsert("test.pb.h", "namespace_scope", context); + TryInsert("test.pb.h", "global_scope", context); + TryInsert("test.pb.h", "class_scope:foo.Bar", context); + TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", context); + + TryInsert("test.pb.cc", "includes", context); + TryInsert("test.pb.cc", "namespace_scope", context); + TryInsert("test.pb.cc", "global_scope", context); return true; } void TryInsert(const string& filename, const string& insertion_point, - OutputDirectory* output_directory) const { + GeneratorContext* context) const { scoped_ptr output( - output_directory->OpenForInsert(filename, insertion_point)); + context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } @@ -83,13 +85,13 @@ class TestGenerator : public CodeGenerator { // not verify that they are correctly-placed; that would require actually // compiling the output which is a bit more than I care to do for this test. TEST(CppPluginTest, PluginTest) { - File::WriteStringToFileOrDie( - "syntax = \"proto2\";\n" - "package foo;\n" - "message Bar {\n" - " message Baz {}\n" - "}\n", - TestTempDir() + "/test.proto"); + GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto", + "syntax = \"proto2\";\n" + "package foo;\n" + "message Bar {\n" + " message Baz {}\n" + "}\n", + true)); google::protobuf::compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index a69c48b..cb72fb1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -80,8 +80,9 @@ int FixedSize(FieldDescriptor::Type type) { } void SetPrimitiveVariables(const FieldDescriptor* descriptor, - map* variables) { - SetCommonFieldVariables(descriptor, variables); + map* variables, + const Options& options) { + SetCommonFieldVariables(descriptor, variables, options); (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type()); (*variables)["default"] = DefaultValue(descriptor); (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); @@ -92,6 +93,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, (*variables)["wire_format_field_type"] = "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name( static_cast(descriptor->type())); + (*variables)["full_name"] = descriptor->full_name(); } } // namespace @@ -99,9 +101,10 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, // =================================================================== PrimitiveFieldGenerator:: -PrimitiveFieldGenerator(const FieldDescriptor* descriptor) +PrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) : descriptor_(descriptor) { - SetPrimitiveVariables(descriptor, &variables_); + SetPrimitiveVariables(descriptor, &variables_, options); } PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} @@ -122,11 +125,13 @@ void PrimitiveFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline $type$ $classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_;\n" "}\n" "inline void $classname$::set_$name$($type$ value) {\n" - " _set_bit($index$);\n" + " set_has_$name$();\n" " $name$_ = value;\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n"); } @@ -156,7 +161,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" " $type$, $wire_format_field_type$>(\n" " input, &$name$_)));\n" - "_set_bit($index$);\n"); + "set_has_$name$();\n"); } void PrimitiveFieldGenerator:: @@ -189,10 +194,67 @@ GenerateByteSize(io::Printer* printer) const { // =================================================================== +PrimitiveOneofFieldGenerator:: +PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : PrimitiveFieldGenerator(descriptor, options) { + SetCommonOneofFieldVariables(descriptor, &variables_); +} + +PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {} + +void PrimitiveOneofFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$ $classname$::$name$() const {\n" + " if (has_$name$()) {\n" + " return $oneof_prefix$$name$_;\n" + " }\n" + " return $default$;\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " }\n" + " $oneof_prefix$$name$_ = value;\n" + "}\n"); +} + +void PrimitiveOneofFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n"); +} + +void PrimitiveOneofFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + // Don't print any swapping code. Swapping the union will swap this field. +} + +void PrimitiveOneofFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + printer->Print( + variables_, + " $classname$_default_oneof_instance_->$name$_ = $default$;\n"); +} + +void PrimitiveOneofFieldGenerator:: +GenerateMergeFromCodedStream(io::Printer* printer) const { + printer->Print(variables_, + "clear_$oneof_name$();\n" + "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" + " $type$, $wire_format_field_type$>(\n" + " input, &$oneof_prefix$$name$_)));\n" + "set_has_$name$();\n"); +} + +// =================================================================== + RepeatedPrimitiveFieldGenerator:: -RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor) +RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) : descriptor_(descriptor) { - SetPrimitiveVariables(descriptor, &variables_); + SetPrimitiveVariables(descriptor, &variables_, options); if (descriptor->options().packed()) { variables_["packed_reader"] = "ReadPackedPrimitive"; @@ -232,21 +294,26 @@ void RepeatedPrimitiveFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline $type$ $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.Get(index);\n" "}\n" "inline void $classname$::set_$name$(int index, $type$ value) {\n" " $name$_.Set(index, value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "inline void $classname$::add_$name$($type$ value) {\n" " $name$_.Add(value);\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n"); printer->Print(variables_, "inline const ::google::protobuf::RepeatedField< $type$ >&\n" "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" "inline ::google::protobuf::RepeatedField< $type$ >*\n" "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" "}\n"); } @@ -366,7 +433,9 @@ GenerateByteSize(io::Printer* printer) const { " total_size += $tag_size$ +\n" " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n" "}\n" + "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" "_$name$_cached_byte_size_ = data_size;\n" + "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" "total_size += data_size;\n"); } else { printer->Print(variables_, diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h index 8fcd74a..1f66c9d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h @@ -46,7 +46,8 @@ namespace cpp { class PrimitiveFieldGenerator : public FieldGenerator { public: - explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor); + explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~PrimitiveFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -62,16 +63,35 @@ class PrimitiveFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; +class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { + public: + explicit PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~PrimitiveOneofFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + void GenerateMergeFromCodedStream(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator); +}; + class RepeatedPrimitiveFieldGenerator : public FieldGenerator { public: - explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor); + explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~RepeatedPrimitiveFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc index c282568..d20018e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.cc +++ b/src/google/protobuf/compiler/cpp/cpp_service.cc @@ -43,14 +43,14 @@ namespace compiler { namespace cpp { ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor, - const string& dllexport_decl) + const Options& options) : descriptor_(descriptor) { vars_["classname"] = descriptor_->name(); vars_["full_name"] = descriptor_->full_name(); - if (dllexport_decl.empty()) { + if (options.dllexport_decl.empty()) { vars_["dllexport"] = ""; } else { - vars_["dllexport"] = dllexport_decl + " "; + vars_["dllexport"] = options.dllexport_decl + " "; } } diff --git a/src/google/protobuf/compiler/cpp/cpp_service.h b/src/google/protobuf/compiler/cpp/cpp_service.h index 10e9dd3..493f314 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.h +++ b/src/google/protobuf/compiler/cpp/cpp_service.h @@ -37,7 +37,7 @@ #include #include -#include +#include #include namespace google { @@ -55,7 +55,7 @@ class ServiceGenerator { public: // See generator.cc for the meaning of dllexport_decl. explicit ServiceGenerator(const ServiceDescriptor* descriptor, - const string& dllexport_decl); + const Options& options); ~ServiceGenerator(); // Header stuff. diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index ea6809a..d41b5bc 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -46,12 +46,23 @@ namespace cpp { namespace { void SetStringVariables(const FieldDescriptor* descriptor, - map* variables) { - SetCommonFieldVariables(descriptor, variables); - (*variables)["default"] = - "\"" + CEscape(descriptor->default_value_string()) + "\""; + map* variables, + const Options& options) { + SetCommonFieldVariables(descriptor, variables, options); + (*variables)["default"] = DefaultValue(descriptor); + (*variables)["default_length"] = + SimpleItoa(descriptor->default_value_string().length()); + (*variables)["default_variable"] = descriptor->default_value_string().empty() + ? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()" + : "_default_" + FieldName(descriptor) + "_"; (*variables)["pointer_type"] = descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char"; + // NOTE: Escaped here to unblock proto1->proto2 migration. + // TODO(liujisi): Extend this to apply for other conflicting methods. + (*variables)["release_name"] = + SafeFunctionName(descriptor->containing_type(), + descriptor, "release_"); + (*variables)["full_name"] = descriptor->full_name(); } } // namespace @@ -59,18 +70,24 @@ void SetStringVariables(const FieldDescriptor* descriptor, // =================================================================== StringFieldGenerator:: -StringFieldGenerator(const FieldDescriptor* descriptor) +StringFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) : descriptor_(descriptor) { - SetStringVariables(descriptor, &variables_); + SetStringVariables(descriptor, &variables_, options); } StringFieldGenerator::~StringFieldGenerator() {} void StringFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, - "::std::string* $name$_;\n" - "static const ::std::string _default_$name$_;\n"); + printer->Print(variables_, "::std::string* $name$_;\n"); +} + +void StringFieldGenerator:: +GenerateStaticMembers(io::Printer* printer) const { + if (!descriptor_->default_value_string().empty()) { + printer->Print(variables_, "static ::std::string* $default_variable$;\n"); + } } void StringFieldGenerator:: @@ -105,7 +122,10 @@ GenerateAccessorDeclarations(io::Printer* printer) const { "inline void set_$name$(const char* value)$deprecation$;\n" "inline void set_$name$(const $pointer_type$* value, size_t size)" "$deprecation$;\n" - "inline ::std::string* mutable_$name$()$deprecation$;\n"); + "inline ::std::string* mutable_$name$()$deprecation$;\n" + "inline ::std::string* $release_name$()$deprecation$;\n" + "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n"); + if (descriptor_->options().ctype() != FieldOptions::STRING) { printer->Outdent(); @@ -118,54 +138,80 @@ void StringFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline const ::std::string& $classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" " return *$name$_;\n" "}\n" "inline void $classname$::set_$name$(const ::std::string& value) {\n" - " _set_bit($index$);\n" - " if ($name$_ == &_default_$name$_) {\n" + " set_has_$name$();\n" + " if ($name$_ == $default_variable$) {\n" " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "inline void $classname$::set_$name$(const char* value) {\n" - " _set_bit($index$);\n" - " if ($name$_ == &_default_$name$_) {\n" + " set_has_$name$();\n" + " if ($name$_ == $default_variable$) {\n" " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(value);\n" + " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" "inline " "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n" - " _set_bit($index$);\n" - " if ($name$_ == &_default_$name$_) {\n" + " set_has_$name$();\n" + " if ($name$_ == $default_variable$) {\n" " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(reinterpret_cast(value), size);\n" + " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" "inline ::std::string* $classname$::mutable_$name$() {\n" - " _set_bit($index$);\n" - " if ($name$_ == &_default_$name$_) {\n"); + " set_has_$name$();\n" + " if ($name$_ == $default_variable$) {\n"); if (descriptor_->default_value_string().empty()) { printer->Print(variables_, " $name$_ = new ::std::string;\n"); } else { printer->Print(variables_, - " $name$_ = new ::std::string(_default_$name$_);\n"); + " $name$_ = new ::std::string(*$default_variable$);\n"); } printer->Print(variables_, " }\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_;\n" + "}\n" + "inline ::std::string* $classname$::$release_name$() {\n" + " clear_has_$name$();\n" + " if ($name$_ == $default_variable$) {\n" + " return NULL;\n" + " } else {\n" + " ::std::string* temp = $name$_;\n" + " $name$_ = const_cast< ::std::string*>($default_variable$);\n" + " return temp;\n" + " }\n" + "}\n" + "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + " if ($name$_ != $default_variable$) {\n" + " delete $name$_;\n" + " }\n" + " if ($name$) {\n" + " set_has_$name$();\n" + " $name$_ = $name$;\n" + " } else {\n" + " clear_has_$name$();\n" + " $name$_ = const_cast< ::std::string*>($default_variable$);\n" + " }\n" + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); } void StringFieldGenerator:: GenerateNonInlineAccessorDefinitions(io::Printer* printer) const { - if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "const ::std::string $classname$::_default_$name$_;\n"); - } else { + if (!descriptor_->default_value_string().empty()) { + // Initialized in GenerateDefaultInstanceAllocator. printer->Print(variables_, - "const ::std::string $classname$::_default_$name$_($default$);\n"); + "::std::string* $classname$::$default_variable$ = NULL;\n"); } } @@ -173,13 +219,13 @@ void StringFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { if (descriptor_->default_value_string().empty()) { printer->Print(variables_, - "if ($name$_ != &_default_$name$_) {\n" + "if ($name$_ != $default_variable$) {\n" " $name$_->clear();\n" "}\n"); } else { printer->Print(variables_, - "if ($name$_ != &_default_$name$_) {\n" - " $name$_->assign(_default_$name$_);\n" + "if ($name$_ != $default_variable$) {\n" + " $name$_->assign(*$default_variable$);\n" "}\n"); } } @@ -197,18 +243,35 @@ GenerateSwappingCode(io::Printer* printer) const { void StringFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { printer->Print(variables_, - "$name$_ = const_cast< ::std::string*>(&_default_$name$_);\n"); + "$name$_ = const_cast< ::std::string*>($default_variable$);\n"); } void StringFieldGenerator:: GenerateDestructorCode(io::Printer* printer) const { printer->Print(variables_, - "if ($name$_ != &_default_$name$_) {\n" + "if ($name$_ != $default_variable$) {\n" " delete $name$_;\n" "}\n"); } void StringFieldGenerator:: +GenerateDefaultInstanceAllocator(io::Printer* printer) const { + if (!descriptor_->default_value_string().empty()) { + printer->Print(variables_, + "$classname$::$default_variable$ =\n" + " new ::std::string($default$, $default_length$);\n"); + } +} + +void StringFieldGenerator:: +GenerateShutdownCode(io::Printer* printer) const { + if (!descriptor_->default_value_string().empty()) { + printer->Print(variables_, + "delete $classname$::$default_variable$;\n"); + } +} + +void StringFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" @@ -216,9 +279,10 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" " this->$name$().data(), this->$name$().length(),\n" - " ::google::protobuf::internal::WireFormat::PARSE);\n"); + " ::google::protobuf::internal::WireFormat::PARSE,\n" + " \"$name$\");\n"); } } @@ -227,12 +291,13 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" " this->$name$().data(), this->$name$().length(),\n" - " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + " ::google::protobuf::internal::WireFormat::SERIALIZE,\n" + " \"$name$\");\n"); } printer->Print(variables_, - "::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" + "::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n" " $number$, this->$name$(), output);\n"); } @@ -241,9 +306,10 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" " this->$name$().data(), this->$name$().length(),\n" - " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + " ::google::protobuf::internal::WireFormat::SERIALIZE,\n" + " \"$name$\");\n"); } printer->Print(variables_, "target =\n" @@ -261,10 +327,130 @@ GenerateByteSize(io::Printer* printer) const { // =================================================================== +StringOneofFieldGenerator:: +StringOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : StringFieldGenerator(descriptor, options) { + SetCommonOneofFieldVariables(descriptor, &variables_); +} + +StringOneofFieldGenerator::~StringOneofFieldGenerator() {} + +void StringOneofFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline const ::std::string& $classname$::$name$() const {\n" + " if (has_$name$()) {\n" + " return *$oneof_prefix$$name$_;\n" + " }\n"); + if (descriptor_->default_value_string().empty()) { + printer->Print(variables_, + " return ::google::protobuf::internal::GetEmptyStringAlreadyInited();\n"); + } else { + printer->Print(variables_, + " return *$default_variable$;\n"); + } + printer->Print(variables_, + "}\n" + "inline void $classname$::set_$name$(const ::std::string& value) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $oneof_prefix$$name$_ = new ::std::string;\n" + " }\n" + " $oneof_prefix$$name$_->assign(value);\n" + "}\n" + "inline void $classname$::set_$name$(const char* value) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $oneof_prefix$$name$_ = new ::std::string;\n" + " }\n" + " $oneof_prefix$$name$_->assign(value);\n" + "}\n" + "inline " + "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $oneof_prefix$$name$_ = new ::std::string;\n" + " }\n" + " $oneof_prefix$$name$_->assign(\n" + " reinterpret_cast(value), size);\n" + "}\n" + "inline ::std::string* $classname$::mutable_$name$() {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n"); + if (descriptor_->default_value_string().empty()) { + printer->Print(variables_, + " $oneof_prefix$$name$_ = new ::std::string;\n"); + } else { + printer->Print(variables_, + " $oneof_prefix$$name$_ = new ::std::string(*$default_variable$);\n"); + } + printer->Print(variables_, + " }\n" + " return $oneof_prefix$$name$_;\n" + "}\n" + "inline ::std::string* $classname$::$release_name$() {\n" + " if (has_$name$()) {\n" + " clear_has_$oneof_name$();\n" + " ::std::string* temp = $oneof_prefix$$name$_;\n" + " $oneof_prefix$$name$_ = NULL;\n" + " return temp;\n" + " } else {\n" + " return NULL;\n" + " }\n" + "}\n" + "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + " clear_$oneof_name$();\n" + " if ($name$) {\n" + " set_has_$name$();\n" + " $oneof_prefix$$name$_ = $name$;\n" + " }\n" + "}\n"); +} + +void StringOneofFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, + "delete $oneof_prefix$$name$_;\n"); +} + +void StringOneofFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + // Don't print any swapping code. Swapping the union will swap this field. +} + +void StringOneofFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + if (!descriptor_->default_value_string().empty()) { + printer->Print(variables_, + " $classname$_default_oneof_instance_->$name$_ = " + "$classname$::$default_variable$;\n"); + } else { + printer->Print(variables_, + " $classname$_default_oneof_instance_->$name$_ = " + "$default_variable$;\n"); + } +} + +void StringOneofFieldGenerator:: +GenerateDestructorCode(io::Printer* printer) const { + printer->Print(variables_, + "if (has_$name$()) {\n" + " delete $oneof_prefix$$name$_;\n" + "}\n"); +} + +// =================================================================== + RepeatedStringFieldGenerator:: -RepeatedStringFieldGenerator(const FieldDescriptor* descriptor) +RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) : descriptor_(descriptor) { - SetStringVariables(descriptor, &variables_); + SetStringVariables(descriptor, &variables_, options); } RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {} @@ -317,43 +503,53 @@ void RepeatedStringFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline const ::std::string& $classname$::$name$(int index) const {\n" - " return $name$_.Get(index);\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return $name$_.$cppget$(index);\n" "}\n" "inline ::std::string* $classname$::mutable_$name$(int index) {\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable(index);\n" "}\n" "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" " $name$_.Mutable(index)->assign(value);\n" "}\n" "inline void $classname$::set_$name$(int index, const char* value) {\n" " $name$_.Mutable(index)->assign(value);\n" + " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" "inline void " "$classname$::set_$name$" "(int index, const $pointer_type$* value, size_t size) {\n" " $name$_.Mutable(index)->assign(\n" " reinterpret_cast(value), size);\n" + " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" "inline ::std::string* $classname$::add_$name$() {\n" " return $name$_.Add();\n" "}\n" "inline void $classname$::add_$name$(const ::std::string& value) {\n" " $name$_.Add()->assign(value);\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n" "inline void $classname$::add_$name$(const char* value) {\n" " $name$_.Add()->assign(value);\n" + " // @@protoc_insertion_point(field_add_char:$full_name$)\n" "}\n" "inline void " "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n" " $name$_.Add()->assign(reinterpret_cast(value), size);\n" + " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n" "}\n"); printer->Print(variables_, "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n" "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n" "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" "}\n"); } @@ -386,9 +582,11 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" - " this->$name$(0).data(), this->$name$(0).length(),\n" - " ::google::protobuf::internal::WireFormat::PARSE);\n"); + "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" + " this->$name$(this->$name$_size() - 1).data(),\n" + " this->$name$(this->$name$_size() - 1).length(),\n" + " ::google::protobuf::internal::WireFormat::PARSE,\n" + " \"$name$\");\n"); } } @@ -399,9 +597,10 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" " this->$name$(i).data(), this->$name$(i).length(),\n" - " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + " ::google::protobuf::internal::WireFormat::SERIALIZE,\n" + " \"$name$\");\n"); } printer->Print(variables_, " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" @@ -416,9 +615,10 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - " ::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" " this->$name$(i).data(), this->$name$(i).length(),\n" - " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + " ::google::protobuf::internal::WireFormat::SERIALIZE,\n" + " \"$name$\");\n"); } printer->Print(variables_, " target = ::google::protobuf::internal::WireFormatLite::\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h index 7f45107..65f605c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h @@ -46,11 +46,13 @@ namespace cpp { class StringFieldGenerator : public FieldGenerator { public: - explicit StringFieldGenerator(const FieldDescriptor* descriptor); + explicit StringFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~StringFieldGenerator(); // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; + void GenerateStaticMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; @@ -59,21 +61,42 @@ class StringFieldGenerator : public FieldGenerator { void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; void GenerateDestructorCode(io::Printer* printer) const; + void GenerateDefaultInstanceAllocator(io::Printer* printer) const; + void GenerateShutdownCode(io::Printer* printer) const; void GenerateMergeFromCodedStream(io::Printer* printer) const; void GenerateSerializeWithCachedSizes(io::Printer* printer) const; void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator); }; +class StringOneofFieldGenerator : public StringFieldGenerator { + public: + explicit StringOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~StringOneofFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + void GenerateDestructorCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator); +}; + class RepeatedStringFieldGenerator : public FieldGenerator { public: - explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor); + explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); ~RepeatedStringFieldGenerator(); // implements FieldGenerator --------------------------------------- diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto index 79971a9..8b9ff5a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto +++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto @@ -36,6 +36,10 @@ // though the same identifiers are used internally by the C++ code generator. +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added + // We don't put this in a package within proto2 because we need to make sure // that the generated code doesn't depend on being in the proto2 namespace. package protobuf_unittest; @@ -94,14 +98,33 @@ message TestConflictingSymbolNames { // Some keywords. optional uint32 int = 30; optional uint32 friend = 31; + optional uint32 class = 37; // The generator used to #define a macro called "DO" inside the .cc file. message DO {} optional DO do = 32; + // Some template parameter names for extensions. + optional int32 field_type = 33; + optional bool is_packed = 34; + + // test conflicting release_$name$. "length" and "do" field in this message + // must remain string or message fields to make the test valid. + optional string release_length = 35; + // A more extreme case, the field name "do" here is a keyword, which will be + // escaped to "do_" already. Test there is no conflict even with escaped field + // names. + optional DO release_do = 36; + extensions 1000 to max; } +message TestConflictingSymbolNamesExtension { + extend TestConflictingSymbolNames { + repeated int32 repeated_int32_ext = 20423638 [packed=true]; + } +} + message DummyMessage {} service TestConflictingMethodNames { diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index a7e852d..3420137 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -44,6 +44,9 @@ // correctly and produces the interfaces we expect, which is why this test // is written this way. +#include + +#include #include #include @@ -51,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -64,7 +68,7 @@ #include #include #include -#include +#include namespace google { namespace protobuf { @@ -74,6 +78,8 @@ namespace cpp { // Can't use an anonymous namespace here due to brokenness of Tru64 compiler. namespace cpp_unittest { +namespace protobuf_unittest = ::protobuf_unittest; + class MockErrorCollector : public MultiFileErrorCollector { public: @@ -144,6 +150,19 @@ TEST(GeneratedMessageTest, Defaults) { &message.optional_import_message()); } +TEST(GeneratedMessageTest, Int32StringConversion) { + EXPECT_EQ("971", Int32ToString(971)); + EXPECT_EQ("(~0x7fffffff)", Int32ToString(kint32min)); + EXPECT_EQ("2147483647", Int32ToString(kint32max)); +} + +TEST(GeneratedMessageTest, Int64StringConversion) { + EXPECT_EQ("GOOGLE_LONGLONG(971)", Int64ToString(971)); + EXPECT_EQ("GOOGLE_LONGLONG(-2147483648)", Int64ToString(kint32min)); + EXPECT_EQ("GOOGLE_LONGLONG(~0x7fffffffffffffff)", Int64ToString(kint64min)); + EXPECT_EQ("GOOGLE_LONGLONG(9223372036854775807)", Int64ToString(kint64max)); +} + TEST(GeneratedMessageTest, FloatingPointDefaults) { const unittest::TestExtremeDefaultValues& extreme_default = unittest::TestExtremeDefaultValues::default_instance(); @@ -167,6 +186,22 @@ TEST(GeneratedMessageTest, FloatingPointDefaults) { EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float()); } +TEST(GeneratedMessageTest, Trigraph) { + const unittest::TestExtremeDefaultValues& extreme_default = + unittest::TestExtremeDefaultValues::default_instance(); + + EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph()); +} + +TEST(GeneratedMessageTest, ExtremeSmallIntegerDefault) { + const unittest::TestExtremeDefaultValues& extreme_default = + unittest::TestExtremeDefaultValues::default_instance(); + EXPECT_EQ(~0x7fffffff, kint32min); + EXPECT_EQ(GOOGLE_LONGLONG(~0x7fffffffffffffff), kint64min); + EXPECT_EQ(kint32min, extreme_default.really_small_int32()); + EXPECT_EQ(kint64min, extreme_default.really_small_int64()); +} + TEST(GeneratedMessageTest, Accessors) { // Set every field to a unique value then go back and check all those // values. @@ -195,6 +230,96 @@ TEST(GeneratedMessageTest, MutableStringDefault) { EXPECT_EQ("hello", *message.mutable_default_string()); } +TEST(GeneratedMessageTest, StringDefaults) { + unittest::TestExtremeDefaultValues message; + // Check if '\000' can be used in default string value. + EXPECT_EQ(string("hel\000lo", 6), message.string_with_zero()); + EXPECT_EQ(string("wor\000ld", 6), message.bytes_with_zero()); +} + +TEST(GeneratedMessageTest, ReleaseString) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + unittest::TestAllTypes message; + + EXPECT_EQ(NULL, message.release_default_string()); + EXPECT_FALSE(message.has_default_string()); + EXPECT_EQ("hello", message.default_string()); + + message.set_default_string("blah"); + EXPECT_TRUE(message.has_default_string()); + scoped_ptr str(message.release_default_string()); + EXPECT_FALSE(message.has_default_string()); + ASSERT_TRUE(str != NULL); + EXPECT_EQ("blah", *str); + + EXPECT_EQ(NULL, message.release_default_string()); + EXPECT_FALSE(message.has_default_string()); + EXPECT_EQ("hello", message.default_string()); +} + +TEST(GeneratedMessageTest, ReleaseMessage) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + unittest::TestAllTypes message; + + EXPECT_EQ(NULL, message.release_optional_nested_message()); + EXPECT_FALSE(message.has_optional_nested_message()); + + message.mutable_optional_nested_message()->set_bb(1); + scoped_ptr nest( + message.release_optional_nested_message()); + EXPECT_FALSE(message.has_optional_nested_message()); + ASSERT_TRUE(nest != NULL); + EXPECT_EQ(1, nest->bb()); + + EXPECT_EQ(NULL, message.release_optional_nested_message()); + EXPECT_FALSE(message.has_optional_nested_message()); +} + +TEST(GeneratedMessageTest, SetAllocatedString) { + // Check that set_allocated_foo() works for strings. + unittest::TestAllTypes message; + + EXPECT_FALSE(message.has_optional_string()); + const string kHello("hello"); + message.set_optional_string(kHello); + EXPECT_TRUE(message.has_optional_string()); + + message.set_allocated_optional_string(NULL); + EXPECT_FALSE(message.has_optional_string()); + EXPECT_EQ("", message.optional_string()); + + message.set_allocated_optional_string(new string(kHello)); + EXPECT_TRUE(message.has_optional_string()); + EXPECT_EQ(kHello, message.optional_string()); +} + +TEST(GeneratedMessageTest, SetAllocatedMessage) { + // Check that set_allocated_foo() can be called in all cases. + unittest::TestAllTypes message; + + EXPECT_FALSE(message.has_optional_nested_message()); + + message.mutable_optional_nested_message()->set_bb(1); + EXPECT_TRUE(message.has_optional_nested_message()); + + message.set_allocated_optional_nested_message(NULL); + EXPECT_FALSE(message.has_optional_nested_message()); + EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(), + &message.optional_nested_message()); + + message.mutable_optional_nested_message()->set_bb(1); + unittest::TestAllTypes::NestedMessage* nest = + message.release_optional_nested_message(); + ASSERT_TRUE(nest != NULL); + EXPECT_FALSE(message.has_optional_nested_message()); + + message.set_allocated_optional_nested_message(nest); + EXPECT_TRUE(message.has_optional_nested_message()); + EXPECT_EQ(1, message.optional_nested_message().bb()); +} + TEST(GeneratedMessageTest, Clear) { // Set every field to a unique value, clear the message, then check that // it is cleared. @@ -282,6 +407,7 @@ TEST(GeneratedMessageTest, CopyFrom) { TestUtil::ExpectAllFieldsSet(message2); } + TEST(GeneratedMessageTest, SwapWithEmpty) { unittest::TestAllTypes message1, message2; TestUtil::SetAllFields(&message1); @@ -376,10 +502,12 @@ TEST(GeneratedMessageTest, CopyAssignmentOperator) { TestUtil::ExpectAllFieldsSet(message2); // Make sure that self-assignment does something sane. - message2 = message2; + message2.operator=(message2); TestUtil::ExpectAllFieldsSet(message2); } +#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \ + !defined(GOOGLE_PROTOBUF_NO_RTTI) TEST(GeneratedMessageTest, UpcastCopyFrom) { // Test the CopyFrom method that takes in the generic const Message& // parameter. @@ -392,6 +520,7 @@ TEST(GeneratedMessageTest, UpcastCopyFrom) { TestUtil::ExpectAllFieldsSet(message2); } +#endif #ifndef PROTOBUF_TEST_NO_DESCRIPTORS @@ -443,7 +572,9 @@ TEST(GeneratedMessageTest, NonEmptyMergeFrom) { TestUtil::ExpectAllFieldsSet(message1); } -#ifdef GTEST_HAS_DEATH_TEST +#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \ + !defined(GOOGLE_PROTOBUF_NO_RTTI) +#ifdef PROTOBUF_HAS_DEATH_TEST TEST(GeneratedMessageTest, MergeFromSelf) { unittest::TestAllTypes message; @@ -452,7 +583,8 @@ TEST(GeneratedMessageTest, MergeFromSelf) { "&from"); } -#endif // GTEST_HAS_DEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS || !GOOGLE_PROTOBUF_NO_RTTI // Test the generated SerializeWithCachedSizesToArray(), TEST(GeneratedMessageTest, SerializationToArray) { @@ -645,6 +777,16 @@ TEST(GeneratedMessageTest, TestConflictingSymbolNames) { message.set_friend_(5); EXPECT_EQ(5, message.friend_()); + + message.set_class_(6); + EXPECT_EQ(6, message.class_()); + + // Instantiate extension template functions to test conflicting template + // parameter names. + typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage; + message.AddExtension(ExtensionMessage::repeated_int32_ext, 123); + EXPECT_EQ(123, + message.GetExtension(ExtensionMessage::repeated_int32_ext, 0)); } #ifndef PROTOBUF_TEST_NO_DESCRIPTORS @@ -716,8 +858,43 @@ TEST(GeneratedMessageTest, TestSpaceUsed) { message1.SpaceUsed()); } +TEST(GeneratedMessageTest, TestOneofSpaceUsed) { + unittest::TestOneof2 message1; + EXPECT_LE(sizeof(unittest::TestOneof2), message1.SpaceUsed()); + + const int empty_message_size = message1.SpaceUsed(); + // Setting primitive types shouldn't affect the space used. + message1.set_foo_int(123); + message1.set_bar_int(12345); + EXPECT_EQ(empty_message_size, message1.SpaceUsed()); + + // Setting a string in oneof to a small value should only increase SpaceUsed() + // by the size of a string object. + message1.set_foo_string("abc"); + EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed()); + + // Setting a string in oneof to a value larger than the string object itself + // should increase SpaceUsed(), because it cannot store the value internally. + message1.set_foo_string(string(sizeof(string) + 1, 'x')); + int min_expected_increase = message1.foo_string().capacity() + + sizeof(string); + EXPECT_LE(empty_message_size + min_expected_increase, + message1.SpaceUsed()); + + // Setting a message in oneof should delete the other fields and increase the + // size by the size of the nested message type. NestedMessage is simple enough + // that it is equal to sizeof(NestedMessage) + message1.mutable_foo_message(); + ASSERT_EQ(sizeof(unittest::TestOneof2::NestedMessage), + message1.foo_message().SpaceUsed()); + EXPECT_EQ(empty_message_size + + sizeof(unittest::TestOneof2::NestedMessage), + message1.SpaceUsed()); +} + #endif // !PROTOBUF_TEST_NO_DESCRIPTORS + TEST(GeneratedMessageTest, FieldConstantValues) { unittest::TestRequired message; EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1); @@ -762,6 +939,9 @@ TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) { case unittest::TestAllTypes::BAZ: i = 3; break; + case unittest::TestAllTypes::NEG: + i = -1; + break; // no default case: We want to make sure the compiler recognizes that // all cases are covered. (GCC warns if you do not cover all cases of // an enum in a switch.) @@ -790,7 +970,7 @@ TEST(GeneratedEnumTest, IsValidValue) { } TEST(GeneratedEnumTest, MinAndMax) { - EXPECT_EQ(unittest::TestAllTypes::FOO, + EXPECT_EQ(unittest::TestAllTypes::NEG, unittest::TestAllTypes::NestedEnum_MIN); EXPECT_EQ(unittest::TestAllTypes::BAZ, unittest::TestAllTypes::NestedEnum_MAX); @@ -809,20 +989,19 @@ TEST(GeneratedEnumTest, MinAndMax) { EXPECT_EQ(12589235, unittest::TestSparseEnum_ARRAYSIZE); // Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE. - void* nullptr = 0; // NULL may be integer-type, not pointer-type. - EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_MIN); - EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_MAX); - EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_ARRAYSIZE); + void* null_pointer = 0; // NULL may be integer-type, not pointer-type. + EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MIN); + EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MAX); + EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_ARRAYSIZE); - EXPECT_NE(nullptr, &unittest::ForeignEnum_MIN); - EXPECT_NE(nullptr, &unittest::ForeignEnum_MAX); - EXPECT_NE(nullptr, &unittest::ForeignEnum_ARRAYSIZE); + EXPECT_NE(null_pointer, &unittest::ForeignEnum_MIN); + EXPECT_NE(null_pointer, &unittest::ForeignEnum_MAX); + EXPECT_NE(null_pointer, &unittest::ForeignEnum_ARRAYSIZE); - // Make sure we can use _MIN, _MAX and _ARRAYSIZE as switch cases. + // Make sure we can use _MIN and _MAX as switch cases. switch (unittest::SPARSE_A) { case unittest::TestSparseEnum_MIN: case unittest::TestSparseEnum_MAX: - case unittest::TestSparseEnum_ARRAYSIZE: break; default: break; @@ -865,6 +1044,20 @@ TEST(GeneratedEnumTest, GetEnumDescriptor) { GetEnumDescriptor()); } +enum NonProtoEnum { + kFoo = 1, +}; + +TEST(GeneratedEnumTest, IsProtoEnumTypeTrait) { + EXPECT_TRUE(is_proto_enum::value); + EXPECT_TRUE(is_proto_enum::value); + EXPECT_TRUE(is_proto_enum::value); + EXPECT_TRUE(is_proto_enum::value); + + EXPECT_FALSE(is_proto_enum::value); + EXPECT_FALSE(is_proto_enum::value); +} + #endif // PROTOBUF_TEST_NO_DESCRIPTORS // =================================================================== @@ -1079,7 +1272,7 @@ TEST_F(GeneratedServiceTest, CallMethod) { TEST_F(GeneratedServiceTest, CallMethodTypeFailure) { // Verify death if we call Foo() with Bar's message types. -#ifdef GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet +#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet EXPECT_DEBUG_DEATH( mock_service_.CallMethod(foo_, &mock_controller_, &foo_request_, &bar_response_, done_.get()), @@ -1090,7 +1283,7 @@ TEST_F(GeneratedServiceTest, CallMethodTypeFailure) { mock_service_.CallMethod(foo_, &mock_controller_, &bar_request_, &foo_response_, done_.get()), "dynamic_cast"); -#endif // GTEST_HAS_DEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST } TEST_F(GeneratedServiceTest, GetPrototypes) { @@ -1164,6 +1357,657 @@ TEST_F(GeneratedServiceTest, NotImplemented) { EXPECT_TRUE(controller.called_); } +// =================================================================== + +class OneofTest : public testing::Test { + protected: + virtual void SetUp() { + } + + void ExpectEnumCasesWork(const unittest::TestOneof2 &message) { + switch (message.foo_case()) { + case unittest::TestOneof2::kFooInt: + EXPECT_TRUE(message.has_foo_int()); + break; + case unittest::TestOneof2::kFooString: + EXPECT_TRUE(message.has_foo_string()); + break; + case unittest::TestOneof2::kFooBytes: + EXPECT_TRUE(message.has_foo_bytes()); + break; + case unittest::TestOneof2::kFooEnum: + EXPECT_TRUE(message.has_foo_enum()); + break; + case unittest::TestOneof2::kFooMessage: + EXPECT_TRUE(message.has_foo_message()); + break; + case unittest::TestOneof2::kFoogroup: + EXPECT_TRUE(message.has_foogroup()); + break; + case unittest::TestOneof2::FOO_NOT_SET: + break; + } + } +}; + +TEST_F(OneofTest, SettingOneFieldClearsOthers) { + unittest::TestOneof2 message; + + message.set_foo_int(123); + EXPECT_TRUE(message.has_foo_int()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + message.set_foo_string("foo"); + EXPECT_TRUE(message.has_foo_string()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + + message.set_foo_bytes("qux"); + EXPECT_TRUE(message.has_foo_bytes()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + message.set_foo_enum(unittest::TestOneof2::FOO); + EXPECT_TRUE(message.has_foo_enum()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + message.mutable_foo_message()->set_qux_int(234); + EXPECT_TRUE(message.has_foo_message()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + message.mutable_foogroup()->set_a(345); + EXPECT_TRUE(message.has_foogroup()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + + // we repeat this because we didn't test if this properly clears other fields + // at the beginning. + message.set_foo_int(123); + EXPECT_TRUE(message.has_foo_int()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); +} + +TEST_F(OneofTest, EnumCases) { + unittest::TestOneof2 message; + + message.set_foo_int(123); + ExpectEnumCasesWork(message); + message.set_foo_string("foo"); + ExpectEnumCasesWork(message); + message.set_foo_bytes("qux"); + ExpectEnumCasesWork(message); + message.set_foo_enum(unittest::TestOneof2::FOO); + ExpectEnumCasesWork(message); + message.mutable_foo_message()->set_qux_int(234); + ExpectEnumCasesWork(message); + message.mutable_foogroup()->set_a(345); + ExpectEnumCasesWork(message); +} + +TEST_F(OneofTest, PrimitiveType) { + unittest::TestOneof2 message; + // Unset field returns default value + EXPECT_EQ(message.foo_int(), 0); + + message.set_foo_int(123); + EXPECT_TRUE(message.has_foo_int()); + EXPECT_EQ(message.foo_int(), 123); + message.clear_foo_int(); + EXPECT_FALSE(message.has_foo_int()); +} + +TEST_F(OneofTest, EnumType) { + unittest::TestOneof2 message; + // Unset field returns default value + EXPECT_EQ(message.foo_enum(), 1); + + message.set_foo_enum(unittest::TestOneof2::FOO); + EXPECT_TRUE(message.has_foo_enum()); + EXPECT_EQ(message.foo_enum(), unittest::TestOneof2::FOO); + message.clear_foo_enum(); + EXPECT_FALSE(message.has_foo_enum()); +} + +TEST_F(OneofTest, SetString) { + // Check that setting a string field in various ways works + unittest::TestOneof2 message; + + // Unset field returns default value + EXPECT_EQ(message.foo_string(), ""); + + message.set_foo_string("foo"); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "foo"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); + + message.set_foo_string(string("bar")); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "bar"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); + + + message.set_foo_string("qux", 3); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "qux"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); + + message.mutable_foo_string()->assign("quux"); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "quux"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); + + message.set_foo_string("corge"); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "corge"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); +} + +TEST_F(OneofTest, ReleaseString) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + unittest::TestOneof2 message; + + EXPECT_EQ(NULL, message.release_foo_string()); + EXPECT_FALSE(message.has_foo_string()); + + message.set_foo_string("blah"); + EXPECT_TRUE(message.has_foo_string()); + scoped_ptr str(message.release_foo_string()); + EXPECT_FALSE(message.has_foo_string()); + ASSERT_TRUE(str != NULL); + EXPECT_EQ("blah", *str); + + EXPECT_EQ(NULL, message.release_foo_string()); + EXPECT_FALSE(message.has_foo_string()); +} + +TEST_F(OneofTest, SetAllocatedString) { + // Check that set_allocated_foo() works for strings. + unittest::TestOneof2 message; + + EXPECT_FALSE(message.has_foo_string()); + const string kHello("hello"); + message.set_foo_string(kHello); + EXPECT_TRUE(message.has_foo_string()); + + message.set_allocated_foo_string(NULL); + EXPECT_FALSE(message.has_foo_string()); + EXPECT_EQ("", message.foo_string()); + + message.set_allocated_foo_string(new string(kHello)); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(kHello, message.foo_string()); +} + + +TEST_F(OneofTest, SetMessage) { + // Check that setting a message field works + unittest::TestOneof2 message; + + // Unset field returns default instance + EXPECT_EQ(&message.foo_message(), + &unittest::TestOneof2_NestedMessage::default_instance()); + EXPECT_EQ(message.foo_message().qux_int(), 0); + + message.mutable_foo_message()->set_qux_int(234); + EXPECT_TRUE(message.has_foo_message()); + EXPECT_EQ(message.foo_message().qux_int(), 234); + message.clear_foo_message(); + EXPECT_FALSE(message.has_foo_message()); +} + +TEST_F(OneofTest, ReleaseMessage) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + unittest::TestOneof2 message; + + EXPECT_EQ(NULL, message.release_foo_message()); + EXPECT_FALSE(message.has_foo_message()); + + message.mutable_foo_message()->set_qux_int(1); + EXPECT_TRUE(message.has_foo_message()); + scoped_ptr mes( + message.release_foo_message()); + EXPECT_FALSE(message.has_foo_message()); + ASSERT_TRUE(mes != NULL); + EXPECT_EQ(1, mes->qux_int()); + + EXPECT_EQ(NULL, message.release_foo_message()); + EXPECT_FALSE(message.has_foo_message()); +} + +TEST_F(OneofTest, SetAllocatedMessage) { + // Check that set_allocated_foo() works for messages. + unittest::TestOneof2 message; + + EXPECT_FALSE(message.has_foo_message()); + + message.mutable_foo_message()->set_qux_int(1); + EXPECT_TRUE(message.has_foo_message()); + + message.set_allocated_foo_message(NULL); + EXPECT_FALSE(message.has_foo_message()); + EXPECT_EQ(&message.foo_message(), + &unittest::TestOneof2_NestedMessage::default_instance()); + + message.mutable_foo_message()->set_qux_int(1); + unittest::TestOneof2_NestedMessage* mes = message.release_foo_message(); + ASSERT_TRUE(mes != NULL); + EXPECT_FALSE(message.has_foo_message()); + + message.set_allocated_foo_message(mes); + EXPECT_TRUE(message.has_foo_message()); + EXPECT_EQ(1, message.foo_message().qux_int()); +} + + +TEST_F(OneofTest, Clear) { + unittest::TestOneof2 message; + + message.set_foo_int(1); + EXPECT_TRUE(message.has_foo_int()); + message.clear_foo_int(); + EXPECT_FALSE(message.has_foo_int()); +} + +TEST_F(OneofTest, Defaults) { + unittest::TestOneof2 message; + + EXPECT_FALSE(message.has_foo_int()); + EXPECT_EQ(message.foo_int(), 0); + + EXPECT_FALSE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), ""); + + + EXPECT_FALSE(message.has_foo_bytes()); + EXPECT_EQ(message.foo_bytes(), ""); + + EXPECT_FALSE(message.has_foo_enum()); + EXPECT_EQ(message.foo_enum(), 1); + + EXPECT_FALSE(message.has_foo_message()); + EXPECT_EQ(message.foo_message().qux_int(), 0); + + EXPECT_FALSE(message.has_foogroup()); + EXPECT_EQ(message.foogroup().a(), 0); + + + EXPECT_FALSE(message.has_bar_int()); + EXPECT_EQ(message.bar_int(), 5); + + EXPECT_FALSE(message.has_bar_string()); + EXPECT_EQ(message.bar_string(), "STRING"); + + + EXPECT_FALSE(message.has_bar_bytes()); + EXPECT_EQ(message.bar_bytes(), "BYTES"); + + EXPECT_FALSE(message.has_bar_enum()); + EXPECT_EQ(message.bar_enum(), 2); +} + +TEST_F(OneofTest, SwapWithEmpty) { + unittest::TestOneof2 message1, message2; + message1.set_foo_string("FOO"); + EXPECT_TRUE(message1.has_foo_string()); + message1.Swap(&message2); + EXPECT_FALSE(message1.has_foo_string()); + EXPECT_TRUE(message2.has_foo_string()); + EXPECT_EQ(message2.foo_string(), "FOO"); +} + +TEST_F(OneofTest, SwapWithSelf) { + unittest::TestOneof2 message; + message.set_foo_string("FOO"); + EXPECT_TRUE(message.has_foo_string()); + message.Swap(&message); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "FOO"); +} + +TEST_F(OneofTest, SwapBothHasFields) { + unittest::TestOneof2 message1, message2; + + message1.set_foo_string("FOO"); + EXPECT_TRUE(message1.has_foo_string()); + message2.mutable_foo_message()->set_qux_int(1); + EXPECT_TRUE(message2.has_foo_message()); + + message1.Swap(&message2); + EXPECT_FALSE(message1.has_foo_string()); + EXPECT_FALSE(message2.has_foo_message()); + EXPECT_TRUE(message1.has_foo_message()); + EXPECT_EQ(message1.foo_message().qux_int(), 1); + EXPECT_TRUE(message2.has_foo_string()); + EXPECT_EQ(message2.foo_string(), "FOO"); +} + +TEST_F(OneofTest, CopyContructor) { + unittest::TestOneof2 message1; + message1.set_foo_bytes("FOO"); + + unittest::TestOneof2 message2(message1); + EXPECT_TRUE(message2.has_foo_bytes()); + EXPECT_EQ(message2.foo_bytes(), "FOO"); +} + +TEST_F(OneofTest, CopyFrom) { + unittest::TestOneof2 message1, message2; + message1.set_foo_enum(unittest::TestOneof2::BAR); + EXPECT_TRUE(message1.has_foo_enum()); + + message2.CopyFrom(message1); + EXPECT_TRUE(message2.has_foo_enum()); + EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::BAR); + + // Copying from self should be a no-op. + message2.CopyFrom(message2); + EXPECT_TRUE(message2.has_foo_enum()); + EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::BAR); +} + +TEST_F(OneofTest, CopyAssignmentOperator) { + unittest::TestOneof2 message1; + message1.mutable_foo_message()->set_qux_int(123); + EXPECT_TRUE(message1.has_foo_message()); + + unittest::TestOneof2 message2; + message2 = message1; + EXPECT_EQ(message2.foo_message().qux_int(), 123); + + // Make sure that self-assignment does something sane. + message2 = message2; + EXPECT_EQ(message2.foo_message().qux_int(), 123); +} + +TEST_F(OneofTest, UpcastCopyFrom) { + // Test the CopyFrom method that takes in the generic const Message& + // parameter. + unittest::TestOneof2 message1, message2; + message1.mutable_foogroup()->set_a(123); + EXPECT_TRUE(message1.has_foogroup()); + + const Message* source = implicit_cast(&message1); + message2.CopyFrom(*source); + + EXPECT_TRUE(message2.has_foogroup()); + EXPECT_EQ(message2.foogroup().a(), 123); +} + +// Test the generated SerializeWithCachedSizesToArray(), +// This indirectly tests MergePartialFromCodedStream() +// We have to test each field type separately because we cannot set them at the +// same time +TEST_F(OneofTest, SerializationToArray) { + // Primitive type + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_int(123); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_int(), 123); + } + + // String + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_string("foo"); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_string(), "foo"); + } + + + // Bytes + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_bytes("qux"); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_bytes(), "qux"); + } + + // Enum + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_enum(unittest::TestOneof2::FOO); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO); + } + + // Message + { + unittest::TestOneof2 message1, message2; + string data; + message1.mutable_foo_message()->set_qux_int(234); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_message().qux_int(), 234); + } + + // Group + { + unittest::TestOneof2 message1, message2; + string data; + message1.mutable_foogroup()->set_a(345); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foogroup().a(), 345); + } + +} + +// Test the generated SerializeWithCachedSizes() by forcing the buffer to write +// one byte at a time. +// This indirectly tests MergePartialFromCodedStream() +// We have to test each field type separately because we cannot set them at the +// same time +TEST_F(OneofTest, SerializationToStream) { + // Primitive type + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_int(123); + int size = message1.ByteSize(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_int(), 123); + } + + // String + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_string("foo"); + int size = message1.ByteSize(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_string(), "foo"); + } + + + // Bytes + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_bytes("qux"); + int size = message1.ByteSize(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_bytes(), "qux"); + } + + // Enum + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_enum(unittest::TestOneof2::FOO); + int size = message1.ByteSize(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO); + } + + // Message + { + unittest::TestOneof2 message1, message2; + string data; + message1.mutable_foo_message()->set_qux_int(234); + int size = message1.ByteSize(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_message().qux_int(), 234); + } + + // Group + { + unittest::TestOneof2 message1, message2; + string data; + message1.mutable_foogroup()->set_a(345); + int size = message1.ByteSize(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foogroup().a(), 345); + } + +} + +TEST_F(OneofTest, MergeFrom) { + unittest::TestOneof2 message1, message2; + + message1.set_foo_int(123); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_int()); + EXPECT_EQ(message2.foo_int(), 123); + + message1.set_foo_string("foo"); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_string()); + EXPECT_EQ(message2.foo_string(), "foo"); + + + message1.set_foo_bytes("qux"); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_bytes()); + EXPECT_EQ(message2.foo_bytes(), "qux"); + + message1.set_foo_enum(unittest::TestOneof2::FOO); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_enum()); + EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO); + + message1.mutable_foo_message()->set_qux_int(234); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_message()); + EXPECT_EQ(message2.foo_message().qux_int(), 234); + + message1.mutable_foogroup()->set_a(345); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foogroup()); + EXPECT_EQ(message2.foogroup().a(), 345); + +} + } // namespace cpp_unittest } // namespace cpp } // namespace compiler diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.h b/src/google/protobuf/compiler/cpp/cpp_unittest.h new file mode 100644 index 0000000..a3a1d1b --- /dev/null +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.h @@ -0,0 +1,51 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 header declares the namespace google::protobuf::protobuf_unittest in order to expose +// any problems with the generated class names. We use this header to ensure +// unittest.cc will declare the namespace prior to other includes, while obeying +// normal include ordering. +// +// When generating a class name of "foo.Bar" we must ensure we prefix the class +// name with "::", in case the namespace google::protobuf::foo exists. We intentionally +// trigger that case here by declaring google::protobuf::protobuf_unittest. +// +// See ClassName in helpers.h for more details. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__ + +namespace google { +namespace protobuf { +namespace protobuf_unittest {} +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__ diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc index 7689ce9..701ac48 100644 --- a/src/google/protobuf/compiler/importer.cc +++ b/src/google/protobuf/compiler/importer.cc @@ -43,6 +43,7 @@ #include #include +#include #include @@ -124,7 +125,8 @@ bool SourceTreeDescriptorDatabase::FindFileByName( scoped_ptr input(source_tree_->Open(filename)); if (input == NULL) { if (error_collector_ != NULL) { - error_collector_->AddError(filename, -1, 0, "File not found."); + error_collector_->AddError(filename, -1, 0, + source_tree_->GetLastErrorMessage()); } return false; } @@ -186,6 +188,7 @@ Importer::Importer(SourceTree* source_tree, MultiFileErrorCollector* error_collector) : database_(source_tree), pool_(&database_, database_.GetValidationErrorCollector()) { + pool_.EnforceWeakDependencies(true); database_.RecordErrorsTo(error_collector); } @@ -195,10 +198,22 @@ const FileDescriptor* Importer::Import(const string& filename) { return pool_.FindFileByName(filename); } +void Importer::AddUnusedImportTrackFile(const string& file_name) { + pool_.AddUnusedImportTrackFile(file_name); +} + +void Importer::ClearUnusedImportTrackFiles() { + pool_.ClearUnusedImportTrackFiles(); +} + // =================================================================== SourceTree::~SourceTree() {} +string SourceTree::GetLastErrorMessage() { + return "File not found."; +} + DiskSourceTree::DiskSourceTree() {} DiskSourceTree::~DiskSourceTree() {} @@ -231,12 +246,17 @@ static string CanonicalizePath(string path) { // The Win32 API accepts forward slashes as a path delimiter even though // backslashes are standard. Let's avoid confusion and use only forward // slashes. - path = StringReplace(path, "\\", "/", true); + if (HasPrefixString(path, "\\\\")) { + // Avoid converting two leading backslashes. + path = "\\\\" + StringReplace(path.substr(2), "\\", "/", true); + } else { + path = StringReplace(path, "\\", "/", true); + } #endif - vector parts; vector canonical_parts; - SplitStringUsing(path, "/", &parts); // Note: Removes empty parts. + vector parts = Split( + path, "/", true); // Note: Removes empty parts. for (int i = 0; i < parts.size(); i++) { if (parts[i] == ".") { // Ignore. @@ -244,7 +264,7 @@ static string CanonicalizePath(string path) { canonical_parts.push_back(parts[i]); } } - string result = JoinStrings(canonical_parts, "/"); + string result = Join(canonical_parts, "/"); if (!path.empty() && path[0] == '/') { // Restore leading slash. result = '/' + result; @@ -390,8 +410,8 @@ DiskSourceTree::DiskFileToVirtualFile( bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file, string* disk_file) { - scoped_ptr stream(OpenVirtualFile(virtual_file, - disk_file)); + scoped_ptr stream( + OpenVirtualFile(virtual_file, disk_file)); return stream != NULL; } @@ -399,6 +419,10 @@ io::ZeroCopyInputStream* DiskSourceTree::Open(const string& filename) { return OpenVirtualFile(filename, NULL); } +string DiskSourceTree::GetLastErrorMessage() { + return last_error_message_; +} + io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( const string& virtual_file, string* disk_file) { @@ -407,6 +431,8 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( // We do not allow importing of paths containing things like ".." or // consecutive slashes since the compiler expects files to be uniquely // identified by file name. + last_error_message_ = "Backslashes, consecutive slashes, \".\", or \"..\" " + "are not allowed in the virtual path"; return NULL; } @@ -424,13 +450,13 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( if (errno == EACCES) { // The file exists but is not readable. - // TODO(kenton): Find a way to report this more nicely. - GOOGLE_LOG(WARNING) << "Read access is denied for file: " << temp_disk_file; + last_error_message_ = "Read access is denied for file: " + + temp_disk_file; return NULL; } } } - + last_error_message_ = "File not found."; return NULL; } diff --git a/src/google/protobuf/compiler/importer.h b/src/google/protobuf/compiler/importer.h index 7a2efc2..0171d2f 100644 --- a/src/google/protobuf/compiler/importer.h +++ b/src/google/protobuf/compiler/importer.h @@ -166,6 +166,9 @@ class LIBPROTOBUF_EXPORT Importer { return &pool_; } + void AddUnusedImportTrackFile(const string& file_name); + void ClearUnusedImportTrackFiles(); + private: SourceTreeDescriptorDatabase database_; DescriptorPool pool_; @@ -204,6 +207,13 @@ class LIBPROTOBUF_EXPORT SourceTree { // contain "." or ".." components. virtual io::ZeroCopyInputStream* Open(const string& filename) = 0; + // If Open() returns NULL, calling this method immediately will return an + // description of the error. + // Subclasses should implement this method and return a meaningful value for + // better error reporting. + // TODO(xiaofeng): change this to a pure virtual function. + virtual string GetLastErrorMessage(); + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree); }; @@ -273,17 +283,21 @@ class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree { bool VirtualFileToDiskFile(const string& virtual_file, string* disk_file); // implements SourceTree ------------------------------------------- - io::ZeroCopyInputStream* Open(const string& filename); + virtual io::ZeroCopyInputStream* Open(const string& filename); + + virtual string GetLastErrorMessage(); private: struct Mapping { string virtual_path; string disk_path; - inline Mapping(const string& virtual_path, const string& disk_path) - : virtual_path(virtual_path), disk_path(disk_path) {} + inline Mapping(const string& virtual_path_param, + const string& disk_path_param) + : virtual_path(virtual_path_param), disk_path(disk_path_param) {} }; vector mappings_; + string last_error_message_; // Like Open(), but returns the on-disk path in disk_file if disk_file is // non-NULL and the file could be successfully opened. diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc index 56fad56..b54d9b7 100644 --- a/src/google/protobuf/compiler/importer_unittest.cc +++ b/src/google/protobuf/compiler/importer_unittest.cc @@ -33,12 +33,13 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include #include #include #include -#include +#include #include #include #include @@ -92,6 +93,10 @@ class MockSourceTree : public SourceTree { } } + string GetLastErrorMessage() { + return "File not found."; + } + private: hash_map files_; }; @@ -324,6 +329,7 @@ TEST_F(ImporterTest, MapFieldKeyNotScalar) { EXPECT_SUBSTRING("must name a scalar or string", error()); } + // =================================================================== class DiskSourceTreeTest : public testing::Test { @@ -336,7 +342,7 @@ class DiskSourceTreeTest : public testing::Test { if (File::Exists(dirnames_[i])) { File::DeleteRecursively(dirnames_[i], NULL, NULL); } - GOOGLE_CHECK(File::CreateDir(dirnames_[i].c_str(), DEFAULT_FILE_MODE)); + GOOGLE_CHECK_OK(File::CreateDir(dirnames_[i], 0777)); } } @@ -347,11 +353,11 @@ class DiskSourceTreeTest : public testing::Test { } void AddFile(const string& filename, const char* contents) { - File::WriteStringToFileOrDie(contents, filename); + GOOGLE_CHECK_OK(File::SetContents(filename, contents, true)); } void AddSubdir(const string& dirname) { - GOOGLE_CHECK(File::CreateDir(dirname.c_str(), DEFAULT_FILE_MODE)); + GOOGLE_CHECK_OK(File::CreateDir(dirname, 0777)); } void ExpectFileContents(const string& filename, @@ -371,9 +377,11 @@ class DiskSourceTreeTest : public testing::Test { EXPECT_EQ(expected_contents, file_contents); } - void ExpectFileNotFound(const string& filename) { + void ExpectCannotOpenFile(const string& filename, + const string& error_message) { scoped_ptr input(source_tree_.Open(filename)); EXPECT_TRUE(input == NULL); + EXPECT_EQ(error_message, source_tree_.GetLastErrorMessage()); } DiskSourceTree source_tree_; @@ -389,7 +397,7 @@ TEST_F(DiskSourceTreeTest, MapRoot) { source_tree_.MapPath("", dirnames_[0]); ExpectFileContents("foo", "Hello World!"); - ExpectFileNotFound("bar"); + ExpectCannotOpenFile("bar", "File not found."); } TEST_F(DiskSourceTreeTest, MapDirectory) { @@ -400,15 +408,21 @@ TEST_F(DiskSourceTreeTest, MapDirectory) { source_tree_.MapPath("baz", dirnames_[0]); ExpectFileContents("baz/foo", "Hello World!"); - ExpectFileNotFound("baz/bar"); - ExpectFileNotFound("foo"); - ExpectFileNotFound("bar"); + ExpectCannotOpenFile("baz/bar", "File not found."); + ExpectCannotOpenFile("foo", "File not found."); + ExpectCannotOpenFile("bar", "File not found."); // Non-canonical file names should not work. - ExpectFileNotFound("baz//foo"); - ExpectFileNotFound("baz/../baz/foo"); - ExpectFileNotFound("baz/./foo"); - ExpectFileNotFound("baz/foo/"); + ExpectCannotOpenFile("baz//foo", + "Backslashes, consecutive slashes, \".\", or \"..\" are " + "not allowed in the virtual path"); + ExpectCannotOpenFile("baz/../baz/foo", + "Backslashes, consecutive slashes, \".\", or \"..\" are " + "not allowed in the virtual path"); + ExpectCannotOpenFile("baz/./foo", + "Backslashes, consecutive slashes, \".\", or \"..\" are " + "not allowed in the virtual path"); + ExpectCannotOpenFile("baz/foo/", "File not found."); } TEST_F(DiskSourceTreeTest, NoParent) { @@ -420,8 +434,12 @@ TEST_F(DiskSourceTreeTest, NoParent) { source_tree_.MapPath("", dirnames_[0] + "/bar"); ExpectFileContents("baz", "Blah."); - ExpectFileNotFound("../foo"); - ExpectFileNotFound("../bar/baz"); + ExpectCannotOpenFile("../foo", + "Backslashes, consecutive slashes, \".\", or \"..\" are " + "not allowed in the virtual path"); + ExpectCannotOpenFile("../bar/baz", + "Backslashes, consecutive slashes, \".\", or \"..\" are " + "not allowed in the virtual path"); } TEST_F(DiskSourceTreeTest, MapFile) { @@ -431,7 +449,7 @@ TEST_F(DiskSourceTreeTest, MapFile) { source_tree_.MapPath("foo", dirnames_[0] + "/foo"); ExpectFileContents("foo", "Hello World!"); - ExpectFileNotFound("bar"); + ExpectCannotOpenFile("bar", "File not found."); } TEST_F(DiskSourceTreeTest, SearchMultipleDirectories) { @@ -445,7 +463,7 @@ TEST_F(DiskSourceTreeTest, SearchMultipleDirectories) { ExpectFileContents("foo", "Hello World!"); ExpectFileContents("bar", "Goodbye World!"); - ExpectFileNotFound("baz"); + ExpectCannotOpenFile("baz", "File not found."); } TEST_F(DiskSourceTreeTest, OrderingTrumpsSpecificity) { @@ -453,8 +471,7 @@ TEST_F(DiskSourceTreeTest, OrderingTrumpsSpecificity) { // directory is more-specific than a former one. // Create the "bar" directory so we can put a file in it. - ASSERT_TRUE(File::CreateDir((dirnames_[0] + "/bar").c_str(), - DEFAULT_FILE_MODE)); + GOOGLE_CHECK_OK(File::CreateDir(dirnames_[0] + "/bar", 0777)); // Add files and map paths. AddFile(dirnames_[0] + "/bar/foo", "Hello World!"); diff --git a/src/google/protobuf/compiler/java/java_context.cc b/src/google/protobuf/compiler/java/java_context.cc new file mode 100644 index 0000000..67ac0ef --- /dev/null +++ b/src/google/protobuf/compiler/java/java_context.cc @@ -0,0 +1,195 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +#include + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +Context::Context(const FileDescriptor* file) + : name_resolver_(new ClassNameResolver) { + InitializeFieldGeneratorInfo(file); +} + +Context::~Context() { +} + +ClassNameResolver* Context::GetNameResolver() { + return name_resolver_.get(); +} + +namespace { +// Whether two fields have conflicting accessors (assuming name1 and name2 +// are different). name1 and name2 are field1 and field2's camel-case name +// respectively. +bool IsConflicting(const FieldDescriptor* field1, const string& name1, + const FieldDescriptor* field2, const string& name2, + string* info) { + if (field1->is_repeated()) { + if (field2->is_repeated()) { + // Both fields are repeated. + return false; + } else { + // field1 is repeated, and field2 is not. + if (name1 + "Count" == name2) { + *info = "both repeated field \"" + field1->name() + "\" and singular " + + "field \"" + field2->name() + "\" generates the method \"" + + "get" + name1 + "Count()\""; + return true; + } + if (name1 + "List" == name2) { + *info = "both repeated field \"" + field1->name() + "\" and singular " + + "field \"" + field2->name() + "\" generates the method \"" + + "get" + name1 + "List()\""; + return true; + } + // Well, there are obviously many more conflicting cases, but it probably + // doesn't worth the effort to exhaust all of them because they rarely + // happen and as we are continuing adding new methods/changing existing + // methods the number of different conflicting cases will keep growing. + // We can just add more cases here when they are found in the real world. + return false; + } + } else { + if (field2->is_repeated()) { + return IsConflicting(field2, name2, field1, name1, info); + } else { + // None of the two fields are repeated. + return false; + } + } +} +} // namespace + +void Context::InitializeFieldGeneratorInfo(const FileDescriptor* file) { + for (int i = 0; i < file->message_type_count(); ++i) { + InitializeFieldGeneratorInfoForMessage(file->message_type(i)); + } +} + +void Context::InitializeFieldGeneratorInfoForMessage( + const Descriptor* message) { + for (int i = 0; i < message->nested_type_count(); ++i) { + InitializeFieldGeneratorInfoForMessage(message->nested_type(i)); + } + vector fields; + for (int i = 0; i < message->field_count(); ++i) { + fields.push_back(message->field(i)); + } + InitializeFieldGeneratorInfoForFields(fields); + + for (int i = 0; i < message->oneof_decl_count(); ++i) { + const OneofDescriptor* oneof = message->oneof_decl(i); + OneofGeneratorInfo info; + info.name = UnderscoresToCamelCase(oneof->name(), false); + info.capitalized_name = UnderscoresToCamelCase(oneof->name(), true); + oneof_generator_info_map_[oneof] = info; + } +} + +void Context::InitializeFieldGeneratorInfoForFields( + const vector& fields) { + // Find out all fields that conflict with some other field in the same + // message. + vector is_conflict(fields.size()); + vector conflict_reason(fields.size()); + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + const string& name = UnderscoresToCapitalizedCamelCase(field); + for (int j = i + 1; j < fields.size(); ++j) { + const FieldDescriptor* other = fields[j]; + const string& other_name = UnderscoresToCapitalizedCamelCase(other); + if (name == other_name) { + is_conflict[i] = is_conflict[j] = true; + conflict_reason[i] = conflict_reason[j] = + "capitalized name of field \"" + field->name() + + "\" conflicts with field \"" + other->name() + "\""; + } else if (IsConflicting(field, name, other, other_name, + &conflict_reason[j])) { + is_conflict[i] = is_conflict[j] = true; + conflict_reason[i] = conflict_reason[j]; + } + } + if (is_conflict[i]) { + GOOGLE_LOG(WARNING) << "field \"" << field->full_name() << "\" is conflicting " + << "with another field: " << conflict_reason[i]; + } + } + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + FieldGeneratorInfo info; + info.name = UnderscoresToCamelCase(field); + info.capitalized_name = UnderscoresToCapitalizedCamelCase(field); + // For fields conflicting with some other fields, we append the field + // number to their field names in generated code to avoid conflicts. + if (is_conflict[i]) { + info.name += SimpleItoa(field->number()); + info.capitalized_name += SimpleItoa(field->number()); + info.disambiguated_reason = conflict_reason[i]; + } + field_generator_info_map_[field] = info; + } +} + +const FieldGeneratorInfo* Context::GetFieldGeneratorInfo( + const FieldDescriptor* field) const { + const FieldGeneratorInfo* result = + FindOrNull(field_generator_info_map_, field); + if (result == NULL) { + GOOGLE_LOG(FATAL) << "Can not find FieldGeneratorInfo for field: " + << field->full_name(); + } + return result; +} + +const OneofGeneratorInfo* Context::GetOneofGeneratorInfo( + const OneofDescriptor* oneof) const { + const OneofGeneratorInfo* result = + FindOrNull(oneof_generator_info_map_, oneof); + if (result == NULL) { + GOOGLE_LOG(FATAL) << "Can not find OneofGeneratorInfo for oneof: " + << oneof->name(); + } + return result; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_context.h b/src/google/protobuf/compiler/java/java_context.h new file mode 100644 index 0000000..c622b31 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_context.h @@ -0,0 +1,95 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ + +#include +#include +#include + +#include + +namespace google { +namespace protobuf { + class FileDescriptor; + class FieldDescriptor; + class OneofDescriptor; + class Descriptor; + namespace compiler { + namespace java { + class ClassNameResolver; // name_resolver.h + } + } +} // namespace protobuf + +namespace protobuf { +namespace compiler { +namespace java { + +struct FieldGeneratorInfo; +struct OneofGeneratorInfo; +// A context object holds the information that is shared among all code +// generators. +class Context { + public: + explicit Context(const FileDescriptor* file); + ~Context(); + + // Get the name resolver associated with this context. The resolver + // can be used to map descriptors to Java class names. + ClassNameResolver* GetNameResolver(); + + // Get the FieldGeneratorInfo for a given field. + const FieldGeneratorInfo* GetFieldGeneratorInfo( + const FieldDescriptor* field) const; + + // Get the OneofGeneratorInfo for a given oneof. + const OneofGeneratorInfo* GetOneofGeneratorInfo( + const OneofDescriptor* oneof) const; + + private: + void InitializeFieldGeneratorInfo(const FileDescriptor* file); + void InitializeFieldGeneratorInfoForMessage(const Descriptor* message); + void InitializeFieldGeneratorInfoForFields( + const vector& fields); + + scoped_ptr name_resolver_; + map field_generator_info_map_; + map oneof_generator_info_map_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ diff --git a/src/google/protobuf/compiler/java/java_doc_comment.cc b/src/google/protobuf/compiler/java/java_doc_comment.cc new file mode 100644 index 0000000..23127b7 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_doc_comment.cc @@ -0,0 +1,233 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +string EscapeJavadoc(const string& input) { + string result; + result.reserve(input.size() * 2); + + char prev = '*'; + + for (string::size_type i = 0; i < input.size(); i++) { + char c = input[i]; + switch (c) { + case '*': + // Avoid "/*". + if (prev == '/') { + result.append("*"); + } else { + result.push_back(c); + } + break; + case '/': + // Avoid "*/". + if (prev == '*') { + result.append("/"); + } else { + result.push_back(c); + } + break; + case '@': + // '@' starts javadoc tags including the @deprecated tag, which will + // cause a compile-time error if inserted before a declaration that + // does not have a corresponding @Deprecated annotation. + result.append("@"); + break; + case '<': + // Avoid interpretation as HTML. + result.append("<"); + break; + case '>': + // Avoid interpretation as HTML. + result.append(">"); + break; + case '&': + // Avoid interpretation as HTML. + result.append("&"); + break; + case '\\': + // Java interprets Unicode escape sequences anywhere! + result.append("\"); + break; + default: + result.push_back(c); + break; + } + + prev = c; + } + + return result; +} + +static void WriteDocCommentBodyForLocation( + io::Printer* printer, const SourceLocation& location) { + string comments = location.leading_comments.empty() ? + location.trailing_comments : location.leading_comments; + if (!comments.empty()) { + // TODO(kenton): Ideally we should parse the comment text as Markdown and + // write it back as HTML, but this requires a Markdown parser. For now + // we just use

             to get fixed-width text formatting.
            +
            +    // If the comment itself contains block comment start or end markers,
            +    // HTML-escape them so that they don't accidentally close the doc comment.
            +    comments = EscapeJavadoc(comments);
            +
            +    vector lines = Split(comments, "\n");
            +    while (!lines.empty() && lines.back().empty()) {
            +      lines.pop_back();
            +    }
            +
            +    printer->Print(
            +        " *\n"
            +        " * 
            \n");
            +    for (int i = 0; i < lines.size(); i++) {
            +      // Most lines should start with a space.  Watch out for lines that start
            +      // with a /, since putting that right after the leading asterisk will
            +      // close the comment.
            +      if (!lines[i].empty() && lines[i][0] == '/') {
            +        printer->Print(" * $line$\n", "line", lines[i]);
            +      } else {
            +        printer->Print(" *$line$\n", "line", lines[i]);
            +      }
            +    }
            +    printer->Print(" * 
            \n"); + } +} + +template +static void WriteDocCommentBody( + io::Printer* printer, const DescriptorType* descriptor) { + SourceLocation location; + if (descriptor->GetSourceLocation(&location)) { + WriteDocCommentBodyForLocation(printer, location); + } +} + +static string FirstLineOf(const string& value) { + string result = value; + + string::size_type pos = result.find_first_of('\n'); + if (pos != string::npos) { + result.erase(pos); + } + + // If line ends in an opening brace, make it "{ ... }" so it looks nice. + if (!result.empty() && result[result.size() - 1] == '{') { + result.append(" ... }"); + } + + return result; +} + +void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) { + printer->Print( + "/**\n" + " * Protobuf type {@code $fullname$}\n", + "fullname", EscapeJavadoc(message->full_name())); + WriteDocCommentBody(printer, message); + printer->Print(" */\n"); +} + +void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) { + // In theory we should have slightly different comments for setters, getters, + // etc., but in practice everyone already knows the difference between these + // so it's redundant information. + + // We use the field declaration as the first line of the comment, e.g.: + // optional string foo = 5; + // This communicates a lot of information about the field in a small space. + // If the field is a group, the debug string might end with {. + printer->Print( + "/**\n" + " * $def$\n", + "def", EscapeJavadoc(FirstLineOf(field->DebugString()))); + WriteDocCommentBody(printer, field); + printer->Print(" */\n"); +} + +void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) { + printer->Print( + "/**\n" + " * Protobuf enum {@code $fullname$}\n", + "fullname", EscapeJavadoc(enum_->full_name())); + WriteDocCommentBody(printer, enum_); + printer->Print(" */\n"); +} + +void WriteEnumValueDocComment(io::Printer* printer, + const EnumValueDescriptor* value) { + printer->Print( + "/**\n" + " * $def$\n", + "def", EscapeJavadoc(FirstLineOf(value->DebugString()))); + WriteDocCommentBody(printer, value); + printer->Print(" */\n"); +} + +void WriteServiceDocComment(io::Printer* printer, + const ServiceDescriptor* service) { + printer->Print( + "/**\n" + " * Protobuf service {@code $fullname$}\n", + "fullname", EscapeJavadoc(service->full_name())); + WriteDocCommentBody(printer, service); + printer->Print(" */\n"); +} + +void WriteMethodDocComment(io::Printer* printer, + const MethodDescriptor* method) { + printer->Print( + "/**\n" + " * $def$\n", + "def", EscapeJavadoc(FirstLineOf(method->DebugString()))); + WriteDocCommentBody(printer, method); + printer->Print(" */\n"); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_doc_comment.h b/src/google/protobuf/compiler/java/java_doc_comment.h new file mode 100644 index 0000000..7244d9b --- /dev/null +++ b/src/google/protobuf/compiler/java/java_doc_comment.h @@ -0,0 +1,69 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ + +#include + +namespace google { +namespace protobuf { + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +void WriteMessageDocComment(io::Printer* printer, const Descriptor* message); +void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field); +void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_); +void WriteEnumValueDocComment(io::Printer* printer, + const EnumValueDescriptor* value); +void WriteServiceDocComment(io::Printer* printer, + const ServiceDescriptor* service); +void WriteMethodDocComment(io::Printer* printer, + const MethodDescriptor* method); + +// Exposed for testing only. +LIBPROTOC_EXPORT string EscapeJavadoc(const string& input); + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ diff --git a/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc b/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc new file mode 100644 index 0000000..41ea9f4 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc @@ -0,0 +1,67 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) + +#include + +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { +namespace { + +TEST(JavaDocCommentTest, Escaping) { + EXPECT_EQ("foo /* bar */ baz", EscapeJavadoc("foo /* bar */ baz")); + EXPECT_EQ("foo /*/ baz", EscapeJavadoc("foo /*/ baz")); + EXPECT_EQ("{@foo}", EscapeJavadoc("{@foo}")); + EXPECT_EQ("<i>&</i>", EscapeJavadoc("&")); + EXPECT_EQ("foo\u1234bar", EscapeJavadoc("foo\\u1234bar")); + EXPECT_EQ("@deprecated", EscapeJavadoc("@deprecated")); +} + +// TODO(kenton): It's hard to write a robust test of the doc comments -- we +// can only really compare the output against a golden value, which is a +// fairly tedious and fragile testing strategy. If we want to go that route, +// it probably makes sense to bite the bullet and write a test that compares +// the whole generated output for unittest.proto against a golden value, with +// a very simple script that can be run to regenerate it with the latest code. +// This would mean that updates to the golden file would have to be included +// in any change to the code generator, which would actually be fairly useful +// as it allows the reviewer to see clearly how the generated code is +// changing. + +} // namespace +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc index 85e39f5..cd84cf8 100644 --- a/src/google/protobuf/compiler/java/java_enum.cc +++ b/src/google/protobuf/compiler/java/java_enum.cc @@ -35,8 +35,11 @@ #include #include +#include #include +#include #include +#include #include #include #include @@ -46,8 +49,22 @@ namespace protobuf { namespace compiler { namespace java { -EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) - : descriptor_(descriptor) { +namespace { +bool EnumHasCustomOptions(const EnumDescriptor* descriptor) { + if (descriptor->options().unknown_fields().field_count() > 0) return true; + for (int i = 0; i < descriptor->value_count(); ++i) { + const EnumValueDescriptor* value = descriptor->value(i); + if (value->options().unknown_fields().field_count() > 0) return true; + } + return false; +} +} // namespace + +EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, + bool immutable_api, + Context* context) + : descriptor_(descriptor), immutable_api_(immutable_api), + name_resolver_(context->GetNameResolver()) { for (int i = 0; i < descriptor_->value_count(); i++) { const EnumValueDescriptor* value = descriptor_->value(i); const EnumValueDescriptor* canonical_value = @@ -67,6 +84,7 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) EnumGenerator::~EnumGenerator() {} void EnumGenerator::Generate(io::Printer* printer) { + WriteEnumDocComment(printer, descriptor_); if (HasDescriptorMethods(descriptor_)) { printer->Print( "public enum $classname$\n" @@ -85,6 +103,10 @@ void EnumGenerator::Generate(io::Printer* printer) { vars["name"] = canonical_values_[i]->name(); vars["index"] = SimpleItoa(canonical_values_[i]->index()); vars["number"] = SimpleItoa(canonical_values_[i]->number()); + WriteEnumValueDocComment(printer, canonical_values_[i]); + if (canonical_values_[i]->options().deprecated()) { + printer->Print("@java.lang.Deprecated\n"); + } printer->Print(vars, "$name$($index$, $number$),\n"); } @@ -100,10 +122,21 @@ void EnumGenerator::Generate(io::Printer* printer) { vars["classname"] = descriptor_->name(); vars["name"] = aliases_[i].value->name(); vars["canonical_name"] = aliases_[i].canonical_value->name(); + WriteEnumValueDocComment(printer, aliases_[i].value); printer->Print(vars, "public static final $classname$ $name$ = $canonical_name$;\n"); } + for (int i = 0; i < descriptor_->value_count(); i++) { + map vars; + vars["name"] = descriptor_->value(i)->name(); + vars["number"] = SimpleItoa(descriptor_->value(i)->number()); + WriteEnumValueDocComment(printer, descriptor_->value(i)); + printer->Print(vars, + "public static final int $name$_VALUE = $number$;\n"); + } + printer->Print("\n"); + // ----------------------------------------------------------------- printer->Print( @@ -138,7 +171,7 @@ void EnumGenerator::Generate(io::Printer* printer) { " internalValueMap =\n" " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" " public $classname$ findValueByNumber(int number) {\n" - " return $classname$.valueOf(number)\n;" + " return $classname$.valueOf(number);\n" " }\n" " };\n" "\n", @@ -164,32 +197,87 @@ void EnumGenerator::Generate(io::Printer* printer) { // at module init time because it wouldn't work with descriptor.proto, but // we can cache the value the first time getDescriptor() is called. if (descriptor_->containing_type() == NULL) { - printer->Print( - " return $file$.getDescriptor().getEnumTypes().get($index$);\n", - "file", ClassName(descriptor_->file()), - "index", SimpleItoa(descriptor_->index())); + if (!MultipleJavaFiles(descriptor_->file(), immutable_api_)) { + printer->Print( + " return $file$.getDescriptor().getEnumTypes().get($index$);\n", + "file", name_resolver_->GetClassName(descriptor_->file(), + immutable_api_), + "index", SimpleItoa(descriptor_->index())); + } else { + printer->Indent(); + if (EnumHasCustomOptions(descriptor_)) { + // We need to load the immutable classes in order to parse custom + // options. However, since file level enums (no outer class) are + // shared by immutable code and mutable code, the immutable classes + // may not exist. So we try to use Java reflection to retrieve the + // descriptor from immutable classes. + printer->Print( + "try {\n" + " java.lang.Class immutableFileClass =\n" + " java.lang.Class.forName(\"$immutable_file_class_name$\");\n" + " @java.lang.SuppressWarnings(\"unchecked\")\n" + " java.lang.reflect.Method m =\n" + " immutableFileClass.getMethod(\"getDescriptor\");\n" + " com.google.protobuf.Descriptors.FileDescriptor file =\n" + " (com.google.protobuf.Descriptors.FileDescriptor)\n" + " m.invoke(immutableFileClass);\n" + " return file.getEnumTypes().get($index$);\n" + "} catch (Exception e) {\n" + // Immutable classes cannot be found. Proceed as if custom options + // don't exist. + "}\n", + "immutable_file_class_name", + name_resolver_->GetImmutableClassName(descriptor_->file()), + "index", SimpleItoa(descriptor_->index())); + } + printer->Print( + "return $immutable_package$.$descriptor_class$.getDescriptor()\n" + " .getEnumTypes().get($index$);\n", + "immutable_package", FileJavaPackage(descriptor_->file(), true), + "descriptor_class", + name_resolver_->GetDescriptorClassName(descriptor_->file()), + "index", SimpleItoa(descriptor_->index())); + printer->Outdent(); + } } else { printer->Print( - " return $parent$.getDescriptor().getEnumTypes().get($index$);\n", - "parent", ClassName(descriptor_->containing_type()), - "index", SimpleItoa(descriptor_->index())); + " return $parent$.$descriptor$.getEnumTypes().get($index$);\n", + "parent", name_resolver_->GetClassName(descriptor_->containing_type(), + immutable_api_), + "descriptor", descriptor_->containing_type()->options() + .no_standard_descriptor_accessor() + ? "getDefaultInstance().getDescriptorForType()" + : "getDescriptor()", + "index", SimpleItoa(descriptor_->index())); } printer->Print( "}\n" "\n" - "private static final $classname$[] VALUES = {\n" - " ", + "private static final $classname$[] VALUES = ", "classname", descriptor_->name()); - for (int i = 0; i < descriptor_->value_count(); i++) { - printer->Print("$name$, ", - "name", descriptor_->value(i)->name()); + if (CanUseEnumValues()) { + // If the constants we are going to output are exactly the ones we + // have declared in the Java enum in the same order, then we can use + // the values() method that the Java compiler automatically generates + // for every enum. + printer->Print("values();\n"); + } else { + printer->Print( + "{\n" + " "); + for (int i = 0; i < descriptor_->value_count(); i++) { + printer->Print("$name$, ", + "name", descriptor_->value(i)->name()); + } + printer->Print( + "\n" + "};\n"); } printer->Print( "\n" - "};\n" "public static $classname$ valueOf(\n" " com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n" " if (desc.getType() != getDescriptor()) {\n" @@ -197,31 +285,26 @@ void EnumGenerator::Generate(io::Printer* printer) { " \"EnumValueDescriptor is not for this type.\");\n" " }\n" " return VALUES[desc.getIndex()];\n" - "}\n", + "}\n" + "\n", "classname", descriptor_->name()); + + // index is only used for reflection; lite implementation does not need it + printer->Print("private final int index;\n"); } // ----------------------------------------------------------------- printer->Print( - "private final int index;\n" - "private final int value;\n" - "private $classname$(int index, int value) {\n" - " this.index = index;\n" - " this.value = value;\n" - "}\n", + "private final int value;\n\n" + "private $classname$(int index, int value) {\n", "classname", descriptor_->name()); - if (HasDescriptorMethods(descriptor_)) { - // Force the static initialization code for the file to run, since it may - // initialize static variables declared in this class. - printer->Print( - "\n" - "static {\n" - " $file$.getDescriptor();\n" - "}\n", - "file", ClassName(descriptor_->file())); + printer->Print(" this.index = index;\n"); } + printer->Print( + " this.value = value;\n" + "}\n"); printer->Print( "\n" @@ -232,6 +315,18 @@ void EnumGenerator::Generate(io::Printer* printer) { printer->Print("}\n\n"); } +bool EnumGenerator::CanUseEnumValues() { + if (canonical_values_.size() != descriptor_->value_count()) { + return false; + } + for (int i = 0; i < descriptor_->value_count(); i++) { + if (descriptor_->value(i)->name() != canonical_values_[i]->name()) { + return false; + } + } + return true; +} + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_enum.h b/src/google/protobuf/compiler/java/java_enum.h index 05ece1f..af0cd15 100644 --- a/src/google/protobuf/compiler/java/java_enum.h +++ b/src/google/protobuf/compiler/java/java_enum.h @@ -41,6 +41,12 @@ namespace google { namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } namespace io { class Printer; // printer.h } @@ -52,7 +58,9 @@ namespace java { class EnumGenerator { public: - explicit EnumGenerator(const EnumDescriptor* descriptor); + explicit EnumGenerator(const EnumDescriptor* descriptor, + bool immutable_api, + Context* context); ~EnumGenerator(); void Generate(io::Printer* printer); @@ -73,6 +81,13 @@ class EnumGenerator { }; vector aliases_; + bool immutable_api_; + + Context* context_; + ClassNameResolver* name_resolver_; + + bool CanUseEnumValues(); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); }; diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc index af6b1cd..cab9bd0 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.cc +++ b/src/google/protobuf/compiler/java/java_enum_field.cc @@ -35,9 +35,12 @@ #include #include -#include #include +#include +#include +#include #include +#include #include #include #include @@ -49,145 +52,456 @@ namespace java { namespace { -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. void SetEnumVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, map* variables) { - (*variables)["name"] = - UnderscoresToCamelCase(descriptor); - (*variables)["capitalized_name"] = - UnderscoresToCapitalizedCamelCase(descriptor); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["type"] = ClassName(descriptor->enum_type()); - (*variables)["default"] = DefaultValue(descriptor); + SetCommonFieldVariables(descriptor, info, variables); + + (*variables)["type"] = + name_resolver->GetImmutableClassName(descriptor->enum_type()); + (*variables)["mutable_type"] = + name_resolver->GetMutableClassName(descriptor->enum_type()); + (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); (*variables)["tag_size"] = SimpleItoa( internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + if (SupportFieldPresence(descriptor->file())) { + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_message"] = + GenerateSetBit(messageBitIndex) + ";"; + (*variables)["set_has_field_bit_builder"] = + GenerateSetBit(builderBitIndex) + ";"; + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex) + ";"; + + (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + } else { + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["set_has_field_bit_builder"] = ""; + (*variables)["clear_has_field_bit_builder"] = ""; + + (*variables)["is_field_present_message"] = + (*variables)["name"] + "_ != " + (*variables)["default"]; + } + + // For repated builders, one bit is used for whether the array is immutable. + (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); + + // For repeated fields, one bit is used for whether the array is immutable + // in the parsing constructor. + (*variables)["get_mutable_bit_parser"] = + GenerateGetBitMutableLocal(builderBitIndex); + (*variables)["set_mutable_bit_parser"] = + GenerateSetBitMutableLocal(builderBitIndex); + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); } } // namespace // =================================================================== -EnumFieldGenerator:: -EnumFieldGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { - SetEnumVariables(descriptor, &variables_); +ImmutableEnumFieldGenerator:: +ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), + name_resolver_(context->GetNameResolver()) { + SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {} + +int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const { + return 1; } -EnumFieldGenerator::~EnumFieldGenerator() {} +int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$();\n"); +} + +void ImmutableEnumFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private boolean has$capitalized_name$;\n" - "private $type$ $name$_;\n" - "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n" - "public $type$ get$capitalized_name$() { return $name$_; }\n"); + "private $type$ $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, - "public boolean has$capitalized_name$() {\n" - " return result.has$capitalized_name$();\n" - "}\n" - "public $type$ get$capitalized_name$() {\n" - " return result.get$capitalized_name$();\n" - "}\n" - "public Builder set$capitalized_name$($type$ value) {\n" + "private $type$ $name$_ = $default$;\n"); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" " if (value == null) {\n" " throw new NullPointerException();\n" " }\n" - " result.has$capitalized_name$ = true;\n" - " result.$name$_ = value;\n" + " $set_has_field_bit_builder$\n" + " $name$_ = value;\n" + " $on_changed$\n" " return this;\n" - "}\n" - "public Builder clear$capitalized_name$() {\n" - " result.has$capitalized_name$ = false;\n" - " result.$name$_ = $default$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $clear_has_field_bit_builder$\n" + " $name$_ = $default$;\n" + " $on_changed$\n" " return this;\n" "}\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for enums +} + +void ImmutableEnumFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $default$;\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $default$;\n" + "$clear_has_field_bit_builder$\n"); +} + +void ImmutableEnumFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); + } else { + printer->Print(variables_, + "if (other.get$capitalized_name$() != $default$) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); + } +} + +void ImmutableEnumFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); + } + printer->Print(variables_, + "result.$name$_ = $name$_;\n"); +} + +void ImmutableEnumFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "int rawValue = input.readEnum();\n" + "$type$ value = $type$.valueOf(rawValue);\n" + "if (value == null) {\n"); + if (UseUnknownFieldSet(descriptor_->containing_type())) { + printer->Print(variables_, + " unknownFields.mergeVarintField($number$, rawValue);\n"); + } else { + printer->Print(variables_, + " unknownFieldsCodedOutput.writeRawVarint32(tag);\n" + " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n"); + } + printer->Print(variables_, + "} else {\n" + " $set_has_field_bit_message$\n" + " $name$_ = value;\n" + "}\n"); +} + +void ImmutableEnumFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // noop for enums +} + +void ImmutableEnumFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_field_present_message$) {\n" + " output.writeEnum($number$, $name$_.getNumber());\n" + "}\n"); +} + +void ImmutableEnumFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" + "if ($is_field_present_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeEnumSize($number$, $name$_.getNumber());\n" "}\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result &&\n" + " (get$capitalized_name$() == other.get$capitalized_name$());\n"); +} + +void ImmutableEnumFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + com.google.protobuf.Internal.hashEnum(\n" + " get$capitalized_name$());\n"); +} + +string ImmutableEnumFieldGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); +} + +// =================================================================== + +ImmutableEnumOneofFieldGenerator:: +ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableEnumFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); +} + +ImmutableEnumOneofFieldGenerator:: +~ImmutableEnumOneofFieldGenerator() {} + +void ImmutableEnumOneofFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n"); +} + +void ImmutableEnumOneofFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + " }\n" + " return this;\n" + "}\n"); +} + +void ImmutableEnumOneofFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - // Nothing to do here for enum types. + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " result.$oneof_name$_ = $oneof_name$_;\n" + "}\n"); } -void EnumFieldGenerator:: +void ImmutableEnumOneofFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "set$capitalized_name$(other.get$capitalized_name$());\n"); +} + +void ImmutableEnumOneofFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "int rawValue = input.readEnum();\n" - "$type$ value = $type$.valueOf(rawValue);\n"); - if (HasUnknownFields(descriptor_->containing_type())) { + "$type$ value = $type$.valueOf(rawValue);\n" + "if (value == null) {\n"); + if (UseUnknownFieldSet(descriptor_->containing_type())) { printer->Print(variables_, - "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" - "} else {\n"); + " unknownFields.mergeVarintField($number$, rawValue);\n"); } else { printer->Print(variables_, - "if (value != null) {\n"); + " unknownFieldsCodedOutput.writeRawVarint32(tag);\n" + " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n"); } printer->Print(variables_, - " set$capitalized_name$(value);\n" + "} else {\n" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" "}\n"); } -void EnumFieldGenerator:: +void ImmutableEnumOneofFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if (has$capitalized_name$()) {\n" - " output.writeEnum($number$, get$capitalized_name$().getNumber());\n" + "if ($has_oneof_case_message$) {\n" + " output.writeEnum($number$, (($type$) $oneof_name$_).getNumber());\n" "}\n"); } -void EnumFieldGenerator:: +void ImmutableEnumOneofFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if (has$capitalized_name$()) {\n" + "if ($has_oneof_case_message$) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSize($number$, get$capitalized_name$().getNumber());\n" + " .computeEnumSize($number$, (($type$) $oneof_name$_).getNumber());\n" "}\n"); } -string EnumFieldGenerator::GetBoxedType() const { - return ClassName(descriptor_->enum_type()); +// =================================================================== + +RepeatedImmutableEnumFieldGenerator:: +RepeatedImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } -// =================================================================== +RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {} -RepeatedEnumFieldGenerator:: -RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { - SetEnumVariables(descriptor, &variables_); +int RepeatedImmutableEnumFieldGenerator::GetNumBitsForMessage() const { + return 0; } -RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} +int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$(int index);\n"); +} + +void RepeatedImmutableEnumFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private java.util.List<$type$> $name$_ =\n" - " java.util.Collections.emptyList();\n" - "public java.util.List<$type$> get$capitalized_name$List() {\n" + "private java.util.List<$type$> $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" " return $name$_;\n" // note: unmodifiable list - "}\n" - "public int get$capitalized_name$Count() { return $name$_.size(); }\n" - "public $type$ get$capitalized_name$(int index) {\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" " return $name$_.get(index);\n" "}\n"); @@ -198,99 +512,165 @@ GenerateMembers(io::Printer* printer) const { } } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, + // One field is the list and the other field keeps track of whether the + // list is immutable. If it's immutable, the invariant is that it must + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a refererence to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + "private java.util.List<$type$> $name$_ =\n" + " java.util.Collections.emptyList();\n" + + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new java.util.ArrayList<$type$>($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, // Note: We return an unmodifiable list because otherwise the caller // could hold on to the returned list and modify it after the message // has been built, thus mutating the message which is supposed to be // immutable. - "public java.util.List<$type$> get$capitalized_name$List() {\n" - " return java.util.Collections.unmodifiableList(result.$name$_);\n" - "}\n" - "public int get$capitalized_name$Count() {\n" - " return result.get$capitalized_name$Count();\n" - "}\n" - "public $type$ get$capitalized_name$(int index) {\n" - " return result.get$capitalized_name$(index);\n" - "}\n" - "public Builder set$capitalized_name$(int index, $type$ value) {\n" + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value) {\n" " if (value == null) {\n" " throw new NullPointerException();\n" " }\n" - " result.$name$_.set(index, value);\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + " $on_changed$\n" " return this;\n" - "}\n" - "public Builder add$capitalized_name$($type$ value) {\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" " if (value == null) {\n" " throw new NullPointerException();\n" " }\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" - " }\n" - " result.$name$_.add(value);\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" " return this;\n" - "}\n" - "public Builder addAll$capitalized_name$(\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder addAll$capitalized_name$(\n" " java.lang.Iterable values) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" - " }\n" - " super.addAll(values, result.$name$_);\n" + " ensure$capitalized_name$IsMutable();\n" + " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" + " values, $name$_);\n" + " $on_changed$\n" " return this;\n" - "}\n" - "public Builder clear$capitalized_name$() {\n" - " result.$name$_ = java.util.Collections.emptyList();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $name$_ = java.util.Collections.emptyList();\n" + " $clear_mutable_bit_builder$;\n" + " $on_changed$\n" " return this;\n" "}\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for enums +} + +void RepeatedImmutableEnumFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - // Initialized inline. + printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n"); +} + +void RepeatedImmutableEnumFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations: + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. printer->Print(variables_, "if (!other.$name$_.isEmpty()) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" " }\n" - " result.$name$_.addAll(other.$name$_);\n" + " $on_changed$\n" "}\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { + // The code below ensures that the result has an immutable list. If our + // list is immutable, we can just reuse it. If not, we make it immutable. printer->Print(variables_, - "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n" - " result.$name$_ =\n" - " java.util.Collections.unmodifiableList(result.$name$_);\n" - "}\n"); + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { // Read and store the enum printer->Print(variables_, "int rawValue = input.readEnum();\n" - "$type$ value = $type$.valueOf(rawValue);\n"); - if (HasUnknownFields(descriptor_->containing_type())) { + "$type$ value = $type$.valueOf(rawValue);\n" + "if (value == null) {\n"); + if (UseUnknownFieldSet(descriptor_->containing_type())) { printer->Print(variables_, - "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" - "} else {\n"); + " unknownFields.mergeVarintField($number$, rawValue);\n"); } else { printer->Print(variables_, - "if (value != null) {\n"); + " unknownFieldsCodedOutput.writeRawVarint32(tag);\n" + " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n"); } printer->Print(variables_, - " add$capitalized_name$(value);\n" + " } else {\n" + " if (!$get_mutable_bit_parser$) {\n" + " $name$_ = new java.util.ArrayList<$type$>();\n" + " $set_mutable_bit_parser$;\n" + " }\n" + " $name$_.add(value);\n" "}\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateParsingCodeFromPacked(io::Printer* printer) const { // Wrap GenerateParsingCode's contents with a while loop. @@ -308,7 +688,15 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { "input.popLimit(oldLimit);\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_mutable_bit_parser$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); +} + +void RepeatedImmutableEnumFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { if (descriptor_->options().packed()) { printer->Print(variables_, @@ -316,18 +704,18 @@ GenerateSerializationCode(io::Printer* printer) const { " output.writeRawVarint32($tag$);\n" " output.writeRawVarint32($name$MemoizedSerializedSize);\n" "}\n" - "for ($type$ element : get$capitalized_name$List()) {\n" - " output.writeEnumNoTag(element.getNumber());\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeEnumNoTag($name$_.get(i).getNumber());\n" "}\n"); } else { printer->Print(variables_, - "for ($type$ element : get$capitalized_name$List()) {\n" - " output.writeEnum($number$, element.getNumber());\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeEnum($number$, $name$_.get(i).getNumber());\n" "}\n"); } } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, "{\n" @@ -335,9 +723,9 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Indent(); printer->Print(variables_, - "for ($type$ element : get$capitalized_name$List()) {\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" " dataSize += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSizeNoTag(element.getNumber());\n" + " .computeEnumSizeNoTag($name$_.get(i).getNumber());\n" "}\n"); printer->Print( "size += dataSize;\n"); @@ -350,7 +738,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { "}"); } else { printer->Print(variables_, - "size += $tag_size$ * get$capitalized_name$List().size();\n"); + "size += $tag_size$ * $name$_.size();\n"); } // cache the data size for packed fields. @@ -363,8 +751,25 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print("}\n"); } -string RepeatedEnumFieldGenerator::GetBoxedType() const { - return ClassName(descriptor_->enum_type()); +void RepeatedImmutableEnumFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedImmutableEnumFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + com.google.protobuf.Internal.hashEnumList(\n" + " get$capitalized_name$List());\n" + "}\n"); +} + +string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h index c54a0fa..a3afb16 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.h +++ b/src/google/protobuf/compiler/java/java_enum_field.h @@ -41,56 +41,113 @@ namespace google { namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } +} + +namespace protobuf { namespace compiler { namespace java { -class EnumFieldGenerator : public FieldGenerator { +class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { public: - explicit EnumFieldGenerator(const FieldDescriptor* descriptor); - ~EnumFieldGenerator(); - - // implements FieldGenerator --------------------------------------- + explicit ImmutableEnumFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableEnumFieldGenerator(); + + // implements ImmutableFieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldGenerator); }; -class RepeatedEnumFieldGenerator : public FieldGenerator { +class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator { public: - explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor); - ~RepeatedEnumFieldGenerator(); + ImmutableEnumOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableEnumOneofFieldGenerator(); - // implements FieldGenerator --------------------------------------- + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldGenerator); +}; + +class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator { + public: + explicit RepeatedImmutableEnumFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~RepeatedImmutableEnumFieldGenerator(); + + // implements ImmutableFieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingCodeFromPacked(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; private: const FieldDescriptor* descriptor_; map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc index 903b0a9..c62dbfa 100644 --- a/src/google/protobuf/compiler/java/java_extension.cc +++ b/src/google/protobuf/compiler/java/java_extension.cc @@ -33,162 +33,168 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include + +#include +#include #include -#include +#include #include +#include namespace google { namespace protobuf { namespace compiler { namespace java { -namespace { - -const char* TypeName(FieldDescriptor::Type field_type) { - switch (field_type) { - case FieldDescriptor::TYPE_INT32 : return "INT32"; - case FieldDescriptor::TYPE_UINT32 : return "UINT32"; - case FieldDescriptor::TYPE_SINT32 : return "SINT32"; - case FieldDescriptor::TYPE_FIXED32 : return "FIXED32"; - case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32"; - case FieldDescriptor::TYPE_INT64 : return "INT64"; - case FieldDescriptor::TYPE_UINT64 : return "UINT64"; - case FieldDescriptor::TYPE_SINT64 : return "SINT64"; - case FieldDescriptor::TYPE_FIXED64 : return "FIXED64"; - case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64"; - case FieldDescriptor::TYPE_FLOAT : return "FLOAT"; - case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE"; - case FieldDescriptor::TYPE_BOOL : return "BOOL"; - case FieldDescriptor::TYPE_STRING : return "STRING"; - case FieldDescriptor::TYPE_BYTES : return "BYTES"; - case FieldDescriptor::TYPE_ENUM : return "ENUM"; - case FieldDescriptor::TYPE_GROUP : return "GROUP"; - case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE"; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; -} - -} - -ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { +ImmutableExtensionGenerator::ImmutableExtensionGenerator( + const FieldDescriptor* descriptor, Context* context) + : descriptor_(descriptor), context_(context), + name_resolver_(context->GetNameResolver()) { if (descriptor_->extension_scope() != NULL) { - scope_ = ClassName(descriptor_->extension_scope()); + scope_ = name_resolver_->GetImmutableClassName( + descriptor_->extension_scope()); } else { - scope_ = ClassName(descriptor_->file()); + scope_ = name_resolver_->GetImmutableClassName(descriptor_->file()); } } -ExtensionGenerator::~ExtensionGenerator() {} - -void ExtensionGenerator::Generate(io::Printer* printer) { - map vars; - vars["name"] = UnderscoresToCamelCase(descriptor_); - vars["containing_type"] = ClassName(descriptor_->containing_type()); - vars["number"] = SimpleItoa(descriptor_->number()); - vars["constant_name"] = FieldConstantName(descriptor_); - vars["lite"] = HasDescriptorMethods(descriptor_->file()) ? "" : "Lite"; +ImmutableExtensionGenerator::~ImmutableExtensionGenerator() {} + +// Initializes the vars referenced in the generated code templates. +void ExtensionGenerator::InitTemplateVars(const FieldDescriptor* descriptor, + const string& scope, + bool immutable, + ClassNameResolver* name_resolver, + map* vars_pointer) { + map &vars = *vars_pointer; + vars["scope"] = scope; + vars["name"] = UnderscoresToCamelCase(descriptor); + vars["containing_type"] = + name_resolver->GetClassName(descriptor->containing_type(), immutable); + vars["number"] = SimpleItoa(descriptor->number()); + vars["constant_name"] = FieldConstantName(descriptor); + vars["index"] = SimpleItoa(descriptor->index()); + vars["default"] = descriptor->is_repeated() ? + "" : DefaultValue(descriptor, immutable, name_resolver); + vars["type_constant"] = FieldTypeName(GetType(descriptor)); + vars["packed"] = descriptor->options().packed() ? "true" : "false"; + vars["enum_map"] = "null"; + vars["prototype"] = "null"; - JavaType java_type = GetJavaType(descriptor_); + JavaType java_type = GetJavaType(descriptor); string singular_type; switch (java_type) { case JAVATYPE_MESSAGE: - vars["type"] = ClassName(descriptor_->message_type()); + singular_type = name_resolver->GetClassName(descriptor->message_type(), + immutable); + vars["prototype"] = singular_type + ".getDefaultInstance()"; break; case JAVATYPE_ENUM: - vars["type"] = ClassName(descriptor_->enum_type()); + singular_type = name_resolver->GetClassName(descriptor->enum_type(), + immutable); + vars["enum_map"] = singular_type + ".internalGetValueMap()"; + break; + case JAVATYPE_STRING: + singular_type = "java.lang.String"; + break; + case JAVATYPE_BYTES: + singular_type = immutable ? "com.google.protobuf.ByteString" : "byte[]"; break; default: - vars["type"] = BoxedPrimitiveTypeName(java_type); + singular_type = BoxedPrimitiveTypeName(java_type); break; } - - printer->Print(vars, - "public static final int $constant_name$ = $number$;\n"); - if (descriptor_->is_repeated()) { - printer->Print(vars, - "public static final\n" - " com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n" - " $containing_type$,\n" - " java.util.List<$type$>> $name$ =\n" - " com.google.protobuf.GeneratedMessage$lite$\n" - " .newGeneratedExtension();\n"); - } else { - printer->Print(vars, - "public static final\n" - " com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n" - " $containing_type$,\n" - " $type$> $name$ =\n" - " com.google.protobuf.GeneratedMessage$lite$\n" - " .newGeneratedExtension();\n"); - } + vars["type"] = descriptor->is_repeated() ? + "java.util.List<" + singular_type + ">" : singular_type; + vars["singular_type"] = singular_type; } -void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) { +void ImmutableExtensionGenerator::Generate(io::Printer* printer) { map vars; - vars["name"] = UnderscoresToCamelCase(descriptor_); - vars["scope"] = scope_; - vars["index"] = SimpleItoa(descriptor_->index()); - vars["extendee"] = ClassName(descriptor_->containing_type()); - vars["default"] = descriptor_->is_repeated() ? "" : DefaultValue(descriptor_); - vars["number"] = SimpleItoa(descriptor_->number()); - vars["type_constant"] = TypeName(GetType(descriptor_)); - vars["packed"] = descriptor_->options().packed() ? "true" : "false"; - vars["enum_map"] = "null"; - vars["prototype"] = "null"; - - JavaType java_type = GetJavaType(descriptor_); - string singular_type; - switch (java_type) { - case JAVATYPE_MESSAGE: - vars["type"] = ClassName(descriptor_->message_type()); - vars["prototype"] = ClassName(descriptor_->message_type()) + - ".getDefaultInstance()"; - break; - case JAVATYPE_ENUM: - vars["type"] = ClassName(descriptor_->enum_type()); - vars["enum_map"] = ClassName(descriptor_->enum_type()) + - ".internalGetValueMap()"; - break; - default: - vars["type"] = BoxedPrimitiveTypeName(java_type); - break; - } + const bool kUseImmutableNames = true; + InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_, + &vars); + printer->Print(vars, + "public static final int $constant_name$ = $number$;\n"); + WriteFieldDocComment(printer, descriptor_); if (HasDescriptorMethods(descriptor_->file())) { - printer->Print(vars, - "$scope$.$name$.internalInit(\n" - " $scope$.getDescriptor().getExtensions().get($index$),\n" - " $type$.class);\n"); + // Non-lite extensions + if (descriptor_->extension_scope() == NULL) { + // Non-nested + printer->Print( + vars, + "public static final\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ = com.google.protobuf.GeneratedMessage\n" + " .newFileScopedGeneratedExtension(\n" + " $singular_type$.class,\n" + " $prototype$);\n"); + } else { + // Nested + printer->Print( + vars, + "public static final\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ = com.google.protobuf.GeneratedMessage\n" + " .newMessageScopedGeneratedExtension(\n" + " $scope$.getDefaultInstance(),\n" + " $index$,\n" + " $singular_type$.class,\n" + " $prototype$);\n"); + } } else { + // Lite extensions if (descriptor_->is_repeated()) { - printer->Print(vars, - "$scope$.$name$.internalInitRepeated(\n" - " $extendee$.getDefaultInstance(),\n" - " $prototype$,\n" - " $enum_map$,\n" - " $number$,\n" - " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" - " $packed$);\n"); + printer->Print( + vars, + "public static final\n" + " com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n" + " .newRepeatedGeneratedExtension(\n" + " $containing_type$.getDefaultInstance(),\n" + " $prototype$,\n" + " $enum_map$,\n" + " $number$,\n" + " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" + " $packed$,\n" + " $singular_type$.class);\n"); } else { - printer->Print(vars, - "$scope$.$name$.internalInitSingular(\n" - " $extendee$.getDefaultInstance(),\n" - " $default$,\n" - " $prototype$,\n" - " $enum_map$,\n" - " $number$,\n" - " com.google.protobuf.WireFormat.FieldType.$type_constant$);\n"); + printer->Print( + vars, + "public static final\n" + " com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n" + " .newSingularGeneratedExtension(\n" + " $containing_type$.getDefaultInstance(),\n" + " $default$,\n" + " $prototype$,\n" + " $enum_map$,\n" + " $number$,\n" + " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" + " $singular_type$.class);\n"); } } } -void ExtensionGenerator::GenerateRegistrationCode(io::Printer* printer) { +void ImmutableExtensionGenerator::GenerateNonNestedInitializationCode( + io::Printer* printer) { + if (descriptor_->extension_scope() == NULL && + HasDescriptorMethods(descriptor_->file())) { + // Only applies to non-nested, non-lite extensions. + printer->Print( + "$name$.internalInit(descriptor.getExtensions().get($index$));\n", + "name", UnderscoresToCamelCase(descriptor_), + "index", SimpleItoa(descriptor_->index())); + } +} + +void ImmutableExtensionGenerator::GenerateRegistrationCode( + io::Printer* printer) { printer->Print( "registry.add($scope$.$name$);\n", "scope", scope_, diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h index 1e42304..69686ef 100644 --- a/src/google/protobuf/compiler/java/java_extension.h +++ b/src/google/protobuf/compiler/java/java_extension.h @@ -35,6 +35,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ +#include #include #include @@ -42,6 +43,12 @@ namespace google { namespace protobuf { class FieldDescriptor; // descriptor.h + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } namespace io { class Printer; // printer.h } @@ -56,17 +63,42 @@ namespace java { // since extensions are just simple identifiers with interesting types. class ExtensionGenerator { public: - explicit ExtensionGenerator(const FieldDescriptor* descriptor); - ~ExtensionGenerator(); + explicit ExtensionGenerator() {} + virtual ~ExtensionGenerator() {} + + virtual void Generate(io::Printer* printer) = 0; + virtual void GenerateNonNestedInitializationCode(io::Printer* printer) = 0; + virtual void GenerateRegistrationCode(io::Printer* printer) = 0; - void Generate(io::Printer* printer); - void GenerateInitializationCode(io::Printer* printer); - void GenerateRegistrationCode(io::Printer* printer); + protected: + static void InitTemplateVars(const FieldDescriptor* descriptor, + const string& scope, + bool immutable, + ClassNameResolver* name_resolver, + map* vars_pointer); private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); +}; + +class ImmutableExtensionGenerator : public ExtensionGenerator { + public: + explicit ImmutableExtensionGenerator(const FieldDescriptor* descriptor, + Context* context); + virtual ~ImmutableExtensionGenerator(); + + virtual void Generate(io::Printer* printer); + virtual void GenerateNonNestedInitializationCode(io::Printer* printer); + virtual void GenerateRegistrationCode(io::Printer* printer); + + protected: const FieldDescriptor* descriptor_; + Context* context_; + ClassNameResolver* name_resolver_; string scope_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionGenerator); }; } // namespace java @@ -74,4 +106,4 @@ class ExtensionGenerator { } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc index 978c8f3..f670477 100644 --- a/src/google/protobuf/compiler/java/java_field.cc +++ b/src/google/protobuf/compiler/java/java_field.cc @@ -33,77 +33,178 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include -#include -#include + +#include + +#include +#include #include +#include +#include #include -#include +#include +#include +#include +#include +#include namespace google { namespace protobuf { namespace compiler { namespace java { -FieldGenerator::~FieldGenerator() {} - -void FieldGenerator::GenerateParsingCodeFromPacked(io::Printer* printer) const { - // Reaching here indicates a bug. Cases are: - // - This FieldGenerator should support packing, but this method should be - // overridden. - // - This FieldGenerator doesn't support packing, and this method should - // never have been called. - GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() " - << "called on field generator that does not support packing."; -} - -FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) - : descriptor_(descriptor), - field_generators_( - new scoped_ptr[descriptor->field_count()]), - extension_generators_( - new scoped_ptr[descriptor->extension_count()]) { +namespace { - // Construct all the FieldGenerators. - for (int i = 0; i < descriptor->field_count(); i++) { - field_generators_[i].reset(MakeGenerator(descriptor->field(i))); - } - for (int i = 0; i < descriptor->extension_count(); i++) { - extension_generators_[i].reset(MakeGenerator(descriptor->extension(i))); - } -} - -FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) { +ImmutableFieldGenerator* MakeImmutableGenerator( + const FieldDescriptor* field, int messageBitIndex, int builderBitIndex, + Context* context) { if (field->is_repeated()) { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: - return new RepeatedMessageFieldGenerator(field); + if (IsLazy(field)) { + return new RepeatedImmutableLazyMessageFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } else { + return new RepeatedImmutableMessageFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } case JAVATYPE_ENUM: - return new RepeatedEnumFieldGenerator(field); + return new RepeatedImmutableEnumFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + case JAVATYPE_STRING: + return new RepeatedImmutableStringFieldGenerator( + field, messageBitIndex, builderBitIndex, context); default: - return new RepeatedPrimitiveFieldGenerator(field); + return new RepeatedImmutablePrimitiveFieldGenerator( + field, messageBitIndex, builderBitIndex, context); } } else { - switch (GetJavaType(field)) { - case JAVATYPE_MESSAGE: - return new MessageFieldGenerator(field); - case JAVATYPE_ENUM: - return new EnumFieldGenerator(field); - default: - return new PrimitiveFieldGenerator(field); + if (field->containing_oneof()) { + switch (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + if (IsLazy(field)) { + return new ImmutableLazyMessageOneofFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } else { + return new ImmutableMessageOneofFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } + case JAVATYPE_ENUM: + return new ImmutableEnumOneofFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + case JAVATYPE_STRING: + return new ImmutableStringOneofFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + default: + return new ImmutablePrimitiveOneofFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } + } else { + switch (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + if (IsLazy(field)) { + return new ImmutableLazyMessageFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } else { + return new ImmutableMessageFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } + case JAVATYPE_ENUM: + return new ImmutableEnumFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + case JAVATYPE_STRING: + return new ImmutableStringFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + default: + return new ImmutablePrimitiveFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } } } } -FieldGeneratorMap::~FieldGeneratorMap() {} -const FieldGenerator& FieldGeneratorMap::get( - const FieldDescriptor* field) const { - GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); - return *field_generators_[field->index()]; +static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) { + // Reaching here indicates a bug. Cases are: + // - This FieldGenerator should support packing, + // but this method should be overridden. + // - This FieldGenerator doesn't support packing, and this method + // should never have been called. + GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() " + << "called on field generator that does not support packing."; } -const FieldGenerator& FieldGeneratorMap::get_extension(int index) const { - return *extension_generators_[index]; +} // namespace + +ImmutableFieldGenerator::~ImmutableFieldGenerator() {} + +void ImmutableFieldGenerator:: +GenerateParsingCodeFromPacked(io::Printer* printer) const { + ReportUnexpectedPackedFieldsCall(printer); +} + +// =================================================================== + +template <> +FieldGeneratorMap::FieldGeneratorMap( + const Descriptor* descriptor, Context* context) + : descriptor_(descriptor), + field_generators_(new scoped_ptr< + ImmutableFieldGenerator>[descriptor->field_count()]) { + + // Construct all the FieldGenerators and assign them bit indices for their + // bit fields. + int messageBitIndex = 0; + int builderBitIndex = 0; + for (int i = 0; i < descriptor->field_count(); i++) { + ImmutableFieldGenerator* generator = MakeImmutableGenerator( + descriptor->field(i), messageBitIndex, builderBitIndex, context); + field_generators_[i].reset(generator); + messageBitIndex += generator->GetNumBitsForMessage(); + builderBitIndex += generator->GetNumBitsForBuilder(); + } +} + +template<> +FieldGeneratorMap::~FieldGeneratorMap() {} + + +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + const FieldGeneratorInfo* info, + map* variables) { + (*variables)["field_name"] = descriptor->name(); + (*variables)["name"] = info->name; + (*variables)["capitalized_name"] = info->capitalized_name; + (*variables)["disambiguated_reason"] = info->disambiguated_reason; + (*variables)["constant_name"] = FieldConstantName(descriptor); + (*variables)["number"] = SimpleItoa(descriptor->number()); +} + +void SetCommonOneofVariables(const FieldDescriptor* descriptor, + const OneofGeneratorInfo* info, + map* variables) { + (*variables)["oneof_name"] = info->name; + (*variables)["oneof_capitalized_name"] = info->capitalized_name; + (*variables)["oneof_index"] = + SimpleItoa(descriptor->containing_oneof()->index()); + (*variables)["set_oneof_case_message"] = info->name + + "Case_ = " + SimpleItoa(descriptor->number()); + (*variables)["clear_oneof_case_message"] = info->name + + "Case_ = 0"; + (*variables)["has_oneof_case_message"] = info->name + + "Case_ == " + SimpleItoa(descriptor->number()); +} + +void PrintExtraFieldInfo(const map& variables, + io::Printer* printer) { + const map::const_iterator it = + variables.find("disambiguated_reason"); + if (it != variables.end() && !it->second.empty()) { + printer->Print( + variables, + "// An alternative name is used for field \"$field_name$\" because:\n" + "// $disambiguated_reason$\n"); + } } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index f5bef7a..a4aa3bc 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -35,14 +35,23 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ +#include +#include #include + #include #include namespace google { namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } namespace io { - class Printer; // printer.h + class Printer; // printer.h } } @@ -50,46 +59,101 @@ namespace protobuf { namespace compiler { namespace java { -class FieldGenerator { +class ImmutableFieldGenerator { public: - FieldGenerator() {} - virtual ~FieldGenerator(); + ImmutableFieldGenerator() {} + virtual ~ImmutableFieldGenerator(); + virtual int GetNumBitsForMessage() const = 0; + virtual int GetNumBitsForBuilder() const = 0; + virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0; virtual void GenerateMembers(io::Printer* printer) const = 0; virtual void GenerateBuilderMembers(io::Printer* printer) const = 0; virtual void GenerateInitializationCode(io::Printer* printer) const = 0; + virtual void GenerateBuilderClearCode(io::Printer* printer) const = 0; virtual void GenerateMergingCode(io::Printer* printer) const = 0; virtual void GenerateBuildingCode(io::Printer* printer) const = 0; virtual void GenerateParsingCode(io::Printer* printer) const = 0; virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const; + virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0; virtual void GenerateSerializationCode(io::Printer* printer) const = 0; virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; + virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer) + const = 0; + + virtual void GenerateEqualsCode(io::Printer* printer) const = 0; + virtual void GenerateHashCode(io::Printer* printer) const = 0; virtual string GetBoxedType() const = 0; private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldGenerator); }; + // Convenience class which constructs FieldGenerators for a Descriptor. +template class FieldGeneratorMap { public: - explicit FieldGeneratorMap(const Descriptor* descriptor); + explicit FieldGeneratorMap(const Descriptor* descriptor, + Context* context); ~FieldGeneratorMap(); - const FieldGenerator& get(const FieldDescriptor* field) const; - const FieldGenerator& get_extension(int index) const; + const FieldGeneratorType& get(const FieldDescriptor* field) const; private: const Descriptor* descriptor_; - scoped_array > field_generators_; - scoped_array > extension_generators_; - - static FieldGenerator* MakeGenerator(const FieldDescriptor* field); + Context* context_; + ClassNameResolver* name_resolver_; + scoped_array > field_generators_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; +template +inline const FieldGeneratorType& +FieldGeneratorMap::get(const FieldDescriptor* field) const { + GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); + return *field_generators_[field->index()]; +} + +// Instantiate template for mutable and immutable maps. +template<> +FieldGeneratorMap:: +FieldGeneratorMap(const Descriptor* descriptor, + Context* context); + +template<> +FieldGeneratorMap::~FieldGeneratorMap(); + + +// Field information used in FieldGeneartors. +struct FieldGeneratorInfo { + string name; + string capitalized_name; + string disambiguated_reason; +}; + +// Oneof information used in OneofFieldGeneartors. +struct OneofGeneratorInfo { + string name; + string capitalized_name; +}; + +// Set some common variables used in variable FieldGenerators. +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + const FieldGeneratorInfo* info, + map* variables); + +// Set some common oneof variables used in OneofFieldGenerators. +void SetCommonOneofVariables(const FieldDescriptor* descriptor, + const OneofGeneratorInfo* info, + map* variables); + +// Print useful comments before a field's accessors. +void PrintExtraFieldInfo(const map& variables, + io::Printer* printer); + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index 7ea127c..5b165b1 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -33,15 +33,23 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include + +#include + +#include #include -#include #include +#include #include #include +#include +#include +#include #include #include #include #include +#include #include namespace google { @@ -51,18 +59,24 @@ namespace java { namespace { -// Recursively searches the given message to see if it contains any extensions. -bool UsesExtensions(const Message& message) { + +// Recursively searches the given message to collect extensions. +// Returns true if all the extensions can be recognized. The extensions will be +// appended in to the extensions parameter. +// Returns false when there are unknown fields, in which case the data in the +// extensions output parameter is not reliable and should be discarded. +bool CollectExtensions(const Message& message, + vector* extensions) { const Reflection* reflection = message.GetReflection(); - // We conservatively assume that unknown fields are extensions. - if (reflection->GetUnknownFields(message).field_count() > 0) return true; + // There are unknown fields that could be extensions, thus this call fails. + if (reflection->GetUnknownFields(message).field_count() > 0) return false; vector fields; reflection->ListFields(message, &fields); for (int i = 0; i < fields.size(); i++) { - if (fields[i]->is_extension()) return true; + if (fields[i]->is_extension()) extensions->push_back(fields[i]); if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) { if (fields[i]->is_repeated()) { @@ -70,25 +84,83 @@ bool UsesExtensions(const Message& message) { for (int j = 0; j < size; j++) { const Message& sub_message = reflection->GetRepeatedMessage(message, fields[i], j); - if (UsesExtensions(sub_message)) return true; + if (!CollectExtensions(sub_message, extensions)) return false; } } else { const Message& sub_message = reflection->GetMessage(message, fields[i]); - if (UsesExtensions(sub_message)) return true; + if (!CollectExtensions(sub_message, extensions)) return false; } } } - return false; + return true; +} + +// Finds all extensions in the given message and its sub-messages. If the +// message contains unknown fields (which could be extensions), then those +// extensions are defined in alternate_pool. +// The message will be converted to a DynamicMessage backed by alternate_pool +// in order to handle this case. +void CollectExtensions(const FileDescriptorProto& file_proto, + const DescriptorPool& alternate_pool, + vector* extensions, + const string& file_data) { + if (!CollectExtensions(file_proto, extensions)) { + // There are unknown fields in the file_proto, which are probably + // extensions. We need to parse the data into a dynamic message based on the + // builder-pool to find out all extensions. + const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName( + file_proto.GetDescriptor()->full_name()); + GOOGLE_CHECK(file_proto_desc) + << "Find unknown fields in FileDescriptorProto when building " + << file_proto.name() + << ". It's likely that those fields are custom options, however, " + "descriptor.proto is not in the transitive dependencies. " + "This normally should not happen. Please report a bug."; + DynamicMessageFactory factory; + scoped_ptr dynamic_file_proto( + factory.GetPrototype(file_proto_desc)->New()); + GOOGLE_CHECK(dynamic_file_proto.get() != NULL); + GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data)); + + // Collect the extensions again from the dynamic message. There should be no + // more unknown fields this time, i.e. all the custom options should be + // parsed as extensions now. + extensions->clear(); + GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions)) + << "Find unknown fields in FileDescriptorProto when building " + << file_proto.name() + << ". It's likely that those fields are custom options, however, " + "those options cannot be recognized in the builder pool. " + "This normally should not happen. Please report a bug."; + } } } // namespace -FileGenerator::FileGenerator(const FileDescriptor* file) - : file_(file), - java_package_(FileJavaPackage(file)), - classname_(FileClassName(file)) {} +FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api) + : file_(file), + java_package_(FileJavaPackage(file, immutable_api)), + message_generators_( + new scoped_ptr[file->message_type_count()]), + extension_generators_( + new scoped_ptr[file->extension_count()]), + context_(new Context(file)), + name_resolver_(context_->GetNameResolver()), + immutable_api_(immutable_api) { + classname_ = name_resolver_->GetFileClassName(file, immutable_api); + generator_factory_.reset( + new ImmutableGeneratorFactory(context_.get())); + for (int i = 0; i < file_->message_type_count(); ++i) { + message_generators_[i].reset( + generator_factory_->NewMessageGenerator(file_->message_type(i))); + } + for (int i = 0; i < file_->extension_count(); ++i) { + extension_generators_[i].reset( + generator_factory_->NewExtensionGenerator(file_->extension(i))); + } +} FileGenerator::~FileGenerator() {} @@ -97,25 +169,7 @@ bool FileGenerator::Validate(string* error) { // problem that leads to Java compile errors that can be hard to understand. // It's especially bad when using the java_multiple_files, since we would // end up overwriting the outer class with one of the inner ones. - - bool found_conflict = false; - for (int i = 0; i < file_->enum_type_count() && !found_conflict; i++) { - if (file_->enum_type(i)->name() == classname_) { - found_conflict = true; - } - } - for (int i = 0; i < file_->message_type_count() && !found_conflict; i++) { - if (file_->message_type(i)->name() == classname_) { - found_conflict = true; - } - } - for (int i = 0; i < file_->service_count() && !found_conflict; i++) { - if (file_->service(i)->name() == classname_) { - found_conflict = true; - } - } - - if (found_conflict) { + if (name_resolver_->HasConflictingClassName(file_, classname_)) { error->assign(file_->name()); error->append( ": Cannot generate Java output because the file's outer class name, \""); @@ -126,7 +180,29 @@ bool FileGenerator::Validate(string* error) { "option to specify a different outer class name for the .proto file."); return false; } - + // If java_outer_classname option is not set and the default outer class name + // conflicts with a type defined in the message, we will append a suffix to + // avoid the conflict. This allows proto1 API protos to be dual-compiled into + // proto2 API without code change. When this happens we'd like to issue an + // warning to let the user know that the outer class name has been changed. + // Although we only do this automatic naming fix for immutable API, mutable + // outer class name will also be affected as it's contructed from immutable + // outer class name with an additional "Mutable" prefix. Since the naming + // change in mutable API is not caused by a naming conflict, we generate the + // warning for immutable API only. + if (immutable_api_ && !file_->options().has_java_outer_classname()) { + string default_classname = + name_resolver_->GetFileDefaultImmutableClassName(file_); + if (default_classname != classname_) { + GOOGLE_LOG(WARNING) << file_->name() << ": The default outer class name, \"" + << default_classname << "\", conflicts with a type " + << "declared in the proto file and an alternative outer " + << "class name is used: \"" << classname_ << "\". To avoid " + << "this warning, please use the java_outer_classname " + << "option to specify a different outer class name for " + << "the .proto file."; + } + } return true; } @@ -160,12 +236,11 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Indent(); for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator(file_->extension(i)).GenerateRegistrationCode(printer); + extension_generators_[i]->GenerateRegistrationCode(printer); } for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator(file_->message_type(i)) - .GenerateExtensionRegistrationCode(printer); + message_generators_[i]->GenerateExtensionRegistrationCode(printer); } printer->Outdent(); @@ -174,16 +249,20 @@ void FileGenerator::Generate(io::Printer* printer) { // ----------------------------------------------------------------- - if (!file_->options().java_multiple_files()) { + if (!MultipleJavaFiles(file_, immutable_api_)) { for (int i = 0; i < file_->enum_type_count(); i++) { - EnumGenerator(file_->enum_type(i)).Generate(printer); + EnumGenerator(file_->enum_type(i), immutable_api_, context_.get()) + .Generate(printer); } for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator(file_->message_type(i)).Generate(printer); + message_generators_[i]->GenerateInterface(printer); + message_generators_[i]->Generate(printer); } if (HasGenericServices(file_)) { for (int i = 0; i < file_->service_count(); i++) { - ServiceGenerator(file_->service(i)).Generate(printer); + scoped_ptr generator( + generator_factory_->NewServiceGenerator(file_->service(i))); + generator->Generate(printer); } } } @@ -191,34 +270,29 @@ void FileGenerator::Generate(io::Printer* printer) { // Extensions must be generated in the outer class since they are values, // not classes. for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator(file_->extension(i)).Generate(printer); + extension_generators_[i]->Generate(printer); } // Static variables. for (int i = 0; i < file_->message_type_count(); i++) { - // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(file_->message_type(i)).GenerateStaticVariables(printer); + message_generators_[i]->GenerateStaticVariables(printer); } printer->Print("\n"); if (HasDescriptorMethods(file_)) { - GenerateEmbeddedDescriptor(printer); + if (immutable_api_) { + GenerateDescriptorInitializationCodeForImmutable(printer); + } else { + GenerateDescriptorInitializationCodeForMutable(printer); + } } else { printer->Print( "static {\n"); printer->Indent(); for (int i = 0; i < file_->message_type_count(); i++) { - // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(file_->message_type(i)) - .GenerateStaticVariableInitializers(printer); - } - - for (int i = 0; i < file_->extension_count(); i++) { - // TODO(kenton): Reuse ExtensionGenerator objects? - ExtensionGenerator(file_->extension(i)) - .GenerateInitializationCode(printer); + message_generators_[i]->GenerateStaticVariableInitializers(printer); } printer->Outdent(); @@ -226,13 +300,6 @@ void FileGenerator::Generate(io::Printer* printer) { "}\n"); } - // Dummy function we can use to force the static initialization block to - // run. Needed by inner classes. Cannot be private due to - // java_multiple_files option. - printer->Print( - "\n" - "public static void internalForceInit() {}\n"); - printer->Print( "\n" "// @@protoc_insertion_point(outer_class_scope)\n"); @@ -241,23 +308,8 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Print("}\n"); } -void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) { - // Embed the descriptor. We simply serialize the entire FileDescriptorProto - // and embed it as a string literal, which is parsed and built into real - // descriptors at initialization time. We unfortunately have to put it in - // a string literal, not a byte array, because apparently using a literal - // byte array causes the Java compiler to generate *instructions* to - // initialize each and every byte of the array, e.g. as if you typed: - // b[0] = 123; b[1] = 456; b[2] = 789; - // This makes huge bytecode files and can easily hit the compiler's internal - // code size limits (error "code to large"). String literals are apparently - // embedded raw, which is what we want. - FileDescriptorProto file_proto; - file_->CopyTo(&file_proto); - - string file_data; - file_proto.SerializeToString(&file_data); - +void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( + io::Printer* printer) { printer->Print( "public static com.google.protobuf.Descriptors.FileDescriptor\n" " getDescriptor() {\n" @@ -265,104 +317,135 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) { "}\n" "private static com.google.protobuf.Descriptors.FileDescriptor\n" " descriptor;\n" - "static {\n" - " java.lang.String[] descriptorData = {\n"); - printer->Indent(); + "static {\n"); printer->Indent(); - // Only write 40 bytes per line. - static const int kBytesPerLine = 40; - for (int i = 0; i < file_data.size(); i += kBytesPerLine) { - if (i > 0) { - // Every 400 lines, start a new string literal, in order to avoid the - // 64k length limit. - if (i % 400 == 0) { - printer->Print(",\n"); - } else { - printer->Print(" +\n"); - } - } - printer->Print("\"$data$\"", - "data", CEscape(file_data.substr(i, kBytesPerLine))); - } - - printer->Outdent(); - printer->Print("\n};\n"); - - // ----------------------------------------------------------------- - // Create the InternalDescriptorAssigner. - - printer->Print( - "com.google.protobuf.Descriptors.FileDescriptor." - "InternalDescriptorAssigner assigner =\n" - " new com.google.protobuf.Descriptors.FileDescriptor." - "InternalDescriptorAssigner() {\n" - " public com.google.protobuf.ExtensionRegistry assignDescriptors(\n" - " com.google.protobuf.Descriptors.FileDescriptor root) {\n" - " descriptor = root;\n"); - - printer->Indent(); - printer->Indent(); - printer->Indent(); + SharedCodeGenerator shared_code_generator(file_); + shared_code_generator.GenerateDescriptors(printer); for (int i = 0; i < file_->message_type_count(); i++) { - // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(file_->message_type(i)) - .GenerateStaticVariableInitializers(printer); + message_generators_[i]->GenerateStaticVariableInitializers(printer); } - for (int i = 0; i < file_->extension_count(); i++) { - // TODO(kenton): Reuse ExtensionGenerator objects? - ExtensionGenerator(file_->extension(i)) - .GenerateInitializationCode(printer); + extension_generators_[i]->GenerateNonNestedInitializationCode(printer); } - if (UsesExtensions(file_proto)) { - // Must construct an ExtensionRegistry containing all possible extensions - // and return it. + // Proto compiler builds a DescriptorPool, which holds all the descriptors to + // generate, when processing the ".proto" files. We call this DescriptorPool + // the parsed pool (a.k.a. file_->pool()). + // + // Note that when users try to extend the (.*)DescriptorProto in their + // ".proto" files, it does not affect the pre-built FileDescriptorProto class + // in proto compiler. When we put the descriptor data in the file_proto, those + // extensions become unknown fields. + // + // Now we need to find out all the extension value to the (.*)DescriptorProto + // in the file_proto message, and prepare an ExtensionRegistry to return. + // + // To find those extensions, we need to parse the data into a dynamic message + // of the FileDescriptor based on the builder-pool, then we can use + // reflections to find all extension fields + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + string file_data; + file_proto.SerializeToString(&file_data); + vector extensions; + CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); + + if (extensions.size() > 0) { + // Must construct an ExtensionRegistry containing all existing extensions + // and use it to parse the descriptor data again to recognize extensions. printer->Print( "com.google.protobuf.ExtensionRegistry registry =\n" - " com.google.protobuf.ExtensionRegistry.newInstance();\n" - "registerAllExtensions(registry);\n"); - for (int i = 0; i < file_->dependency_count(); i++) { - printer->Print( - "$dependency$.registerAllExtensions(registry);\n", - "dependency", ClassName(file_->dependency(i))); + " com.google.protobuf.ExtensionRegistry.newInstance();\n"); + for (int i = 0; i < extensions.size(); i++) { + scoped_ptr generator( + generator_factory_->NewExtensionGenerator(extensions[i])); + generator->GenerateRegistrationCode(printer); } printer->Print( - "return registry;\n"); - } else { - printer->Print( - "return null;\n"); + "com.google.protobuf.Descriptors.FileDescriptor\n" + " .internalUpdateFileDescriptor(descriptor, registry);\n"); } - printer->Outdent(); - printer->Outdent(); - printer->Outdent(); + // Force descriptor initialization of all dependencies. + for (int i = 0; i < file_->dependency_count(); i++) { + if (ShouldIncludeDependency(file_->dependency(i), true)) { + string dependency = + name_resolver_->GetImmutableClassName(file_->dependency(i)); + printer->Print( + "$dependency$.getDescriptor();\n", + "dependency", dependency); + } + } + printer->Outdent(); printer->Print( - " }\n" - " };\n"); + "}\n"); +} - // ----------------------------------------------------------------- - // Invoke internalBuildGeneratedFileFrom() to build the file. +void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* printer) { + printer->Print( + "public static com.google.protobuf.Descriptors.FileDescriptor\n" + " getDescriptor() {\n" + " return descriptor;\n" + "}\n" + "private static com.google.protobuf.Descriptors.FileDescriptor\n" + " descriptor;\n" + "static {\n"); + printer->Indent(); printer->Print( - "com.google.protobuf.Descriptors.FileDescriptor\n" - " .internalBuildGeneratedFileFrom(descriptorData,\n" - " new com.google.protobuf.Descriptors.FileDescriptor[] {\n"); + "descriptor = $immutable_package$.$descriptor_classname$.descriptor;\n", + "immutable_package", FileJavaPackage(file_, true), + "descriptor_classname", name_resolver_->GetDescriptorClassName(file_)); + + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateStaticVariableInitializers(printer); + } + for (int i = 0; i < file_->extension_count(); i++) { + extension_generators_[i]->GenerateNonNestedInitializationCode(printer); + } + + // Check if custom options exist. If any, try to load immutable classes since + // custom options are only represented with immutable messages. + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + string file_data; + file_proto.SerializeToString(&file_data); + vector extensions; + CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); + + if (extensions.size() > 0) { + // Try to load immutable messages' outer class. Its initialization code + // will take care of interpreting custom options. + printer->Print( + "try {\n" + // Note that we have to load the immutable class dynamically here as + // we want the mutable code to be independent from the immutable code + // at compile time. It is required to implement dual-compile for + // mutable and immutable API in blaze. + " java.lang.Class immutableClass = java.lang.Class.forName(\n" + " \"$immutable_classname$\");\n" + "} catch (java.lang.ClassNotFoundException e) {\n" + // The immutable class can not be found. Custom options are left + // as unknown fields. + // TODO(xiaofeng): inform the user with a warning? + "}\n", + "immutable_classname", name_resolver_->GetImmutableClassName(file_)); + } + // Force descriptor initialization of all dependencies. for (int i = 0; i < file_->dependency_count(); i++) { - if (ShouldIncludeDependency(file_->dependency(i))) { + if (ShouldIncludeDependency(file_->dependency(i), false)) { + string dependency = name_resolver_->GetMutableClassName( + file_->dependency(i)); printer->Print( - " $dependency$.getDescriptor(),\n", - "dependency", ClassName(file_->dependency(i))); + "$dependency$.getDescriptor();\n", + "dependency", dependency); } } - printer->Print( - " }, assigner);\n"); - printer->Outdent(); printer->Print( "}\n"); @@ -372,18 +455,22 @@ template static void GenerateSibling(const string& package_dir, const string& java_package, const DescriptorClass* descriptor, - OutputDirectory* output_directory, - vector* file_list) { - string filename = package_dir + descriptor->name() + ".java"; + GeneratorContext* context, + vector* file_list, + const string& name_suffix, + GeneratorClass* generator, + void (GeneratorClass::*pfn)(io::Printer* printer)) { + string filename = package_dir + descriptor->name() + name_suffix + ".java"; file_list->push_back(filename); - scoped_ptr output( - output_directory->Open(filename)); + scoped_ptr output(context->Open(filename)); io::Printer printer(output.get(), '$'); printer.Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "\n"); + "// source: $filename$\n" + "\n", + "filename", descriptor->file()->name()); if (!java_package.empty()) { printer.Print( "package $package$;\n" @@ -391,34 +478,53 @@ static void GenerateSibling(const string& package_dir, "package", java_package); } - GeneratorClass(descriptor).Generate(&printer); + (generator->*pfn)(&printer); } void FileGenerator::GenerateSiblings(const string& package_dir, - OutputDirectory* output_directory, + GeneratorContext* context, vector* file_list) { - if (file_->options().java_multiple_files()) { + if (MultipleJavaFiles(file_, immutable_api_)) { for (int i = 0; i < file_->enum_type_count(); i++) { + EnumGenerator generator(file_->enum_type(i), immutable_api_, + context_.get()); GenerateSibling(package_dir, java_package_, file_->enum_type(i), - output_directory, file_list); + context, file_list, "", + &generator, + &EnumGenerator::Generate); } for (int i = 0; i < file_->message_type_count(); i++) { + if (immutable_api_) { + GenerateSibling(package_dir, java_package_, + file_->message_type(i), + context, file_list, + "OrBuilder", + message_generators_[i].get(), + &MessageGenerator::GenerateInterface); + } GenerateSibling(package_dir, java_package_, file_->message_type(i), - output_directory, file_list); + context, file_list, "", + message_generators_[i].get(), + &MessageGenerator::Generate); } if (HasGenericServices(file_)) { for (int i = 0; i < file_->service_count(); i++) { + scoped_ptr generator( + generator_factory_->NewServiceGenerator(file_->service(i))); GenerateSibling(package_dir, java_package_, file_->service(i), - output_directory, file_list); + context, file_list, "", + generator.get(), + &ServiceGenerator::Generate); } } } } -bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor) { +bool FileGenerator::ShouldIncludeDependency( + const FileDescriptor* descriptor, bool immutable_api) { return true; } diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h index 9e35d33..7f28949 100644 --- a/src/google/protobuf/compiler/java/java_file.h +++ b/src/google/protobuf/compiler/java/java_file.h @@ -35,18 +35,26 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ +#include #include #include #include namespace google { namespace protobuf { - class FileDescriptor; // descriptor.h + class FileDescriptor; // descriptor.h namespace io { - class Printer; // printer.h + class Printer; // printer.h } namespace compiler { - class OutputDirectory; // code_generator.h + class GeneratorContext; // code_generator.h + namespace java { + class Context; // context.h + class MessageGenerator; // message.h + class GeneratorFactory; // generator_factory.h + class ExtensionGenerator; // extension.h + class ClassNameResolver; // name_resolver.h + } } } @@ -56,7 +64,7 @@ namespace java { class FileGenerator { public: - explicit FileGenerator(const FileDescriptor* file); + FileGenerator(const FileDescriptor* file, bool immutable_api = true); ~FileGenerator(); // Checks for problems that would otherwise lead to cryptic compile errors. @@ -70,23 +78,31 @@ class FileGenerator { // files other than the outer file (i.e. one for each message, enum, and // service type). void GenerateSiblings(const string& package_dir, - OutputDirectory* output_directory, + GeneratorContext* generator_context, vector* file_list); const string& java_package() { return java_package_; } const string& classname() { return classname_; } + private: - // Returns whether the dependency should be included in the output file. - // Always returns true for opensource, but used internally at Google to help - // improve compatibility with version 1 of protocol buffers. - bool ShouldIncludeDependency(const FileDescriptor* descriptor); + void GenerateDescriptorInitializationCodeForImmutable(io::Printer* printer); + void GenerateDescriptorInitializationCodeForMutable(io::Printer* printer); + + bool ShouldIncludeDependency(const FileDescriptor* descriptor, + bool immutable_api_); const FileDescriptor* file_; string java_package_; string classname_; - void GenerateEmbeddedDescriptor(io::Printer* printer); + scoped_array > message_generators_; + scoped_array > extension_generators_; + scoped_ptr generator_factory_; + scoped_ptr context_; + ClassNameResolver* name_resolver_; + bool immutable_api_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); }; diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc index 745b55a..42132fa 100644 --- a/src/google/protobuf/compiler/java/java_generator.cc +++ b/src/google/protobuf/compiler/java/java_generator.cc @@ -33,8 +33,13 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include + +#include + #include +#include #include +#include #include #include #include @@ -51,11 +56,8 @@ JavaGenerator::~JavaGenerator() {} bool JavaGenerator::Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { - vector > options; - ParseGeneratorParameter(parameter, &options); - // ----------------------------------------------------------------- // parse generator options @@ -63,50 +65,84 @@ bool JavaGenerator::Generate(const FileDescriptor* file, // per line. string output_list_file; + + vector > options; + ParseGeneratorParameter(parameter, &options); + + bool generate_immutable_code = false; + bool generate_mutable_code = false; + bool generate_shared_code = false; for (int i = 0; i < options.size(); i++) { if (options[i].first == "output_list_file") { output_list_file = options[i].second; + } else if (options[i].first == "immutable") { + generate_immutable_code = true; + } else if (options[i].first == "mutable") { + generate_mutable_code = true; + } else if (options[i].first == "shared") { + generate_shared_code = true; } else { *error = "Unknown generator option: " + options[i].first; return false; } } + // By default we generate immutable code and shared code for immutable API. + if (!generate_immutable_code && !generate_mutable_code && + !generate_shared_code) { + generate_immutable_code = true; + generate_shared_code = true; + } // ----------------------------------------------------------------- - FileGenerator file_generator(file); - if (!file_generator.Validate(error)) { - return false; + vector all_files; + + vector file_generators; + if (generate_immutable_code) { + file_generators.push_back(new FileGenerator(file, /* immutable = */ true)); + } + for (int i = 0; i < file_generators.size(); ++i) { + if (!file_generators[i]->Validate(error)) { + for (int j = 0; j < file_generators.size(); ++j) { + delete file_generators[j]; + } + return false; + } } - string package_dir = - StringReplace(file_generator.java_package(), ".", "/", true); - if (!package_dir.empty()) package_dir += "/"; + for (int i = 0; i < file_generators.size(); ++i) { + FileGenerator* file_generator = file_generators[i]; - vector all_files; + string package_dir = JavaPackageToDir(file_generator->java_package()); + + string java_filename = package_dir; + java_filename += file_generator->classname(); + java_filename += ".java"; + all_files.push_back(java_filename); - string java_filename = package_dir; - java_filename += file_generator.classname(); - java_filename += ".java"; - all_files.push_back(java_filename); + // Generate main java file. + scoped_ptr output( + context->Open(java_filename)); + io::Printer printer(output.get(), '$'); + file_generator->Generate(&printer); - // Generate main java file. - scoped_ptr output( - output_directory->Open(java_filename)); - io::Printer printer(output.get(), '$'); - file_generator.Generate(&printer); + // Generate sibling files. + file_generator->GenerateSiblings(package_dir, context, &all_files); + } - // Generate sibling files. - file_generator.GenerateSiblings(package_dir, output_directory, &all_files); + for (int i = 0; i < file_generators.size(); ++i) { + delete file_generators[i]; + } + file_generators.clear(); // Generate output list if requested. if (!output_list_file.empty()) { // Generate output list. This is just a simple text file placed in a // deterministic location which lists the .java files being generated. scoped_ptr srclist_raw_output( - output_directory->Open(output_list_file)); + context->Open(output_list_file)); io::Printer srclist_printer(srclist_raw_output.get(), '$'); for (int i = 0; i < all_files.size(); i++) { srclist_printer.Print("$filename$\n", "filename", all_files[i]); diff --git a/src/google/protobuf/compiler/java/java_generator.h b/src/google/protobuf/compiler/java/java_generator.h index c91c905..888b8d8 100644 --- a/src/google/protobuf/compiler/java/java_generator.h +++ b/src/google/protobuf/compiler/java/java_generator.h @@ -57,7 +57,7 @@ class LIBPROTOC_EXPORT JavaGenerator : public CodeGenerator { // implements CodeGenerator ---------------------------------------- bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const; private: diff --git a/src/google/protobuf/compiler/java/java_generator_factory.cc b/src/google/protobuf/compiler/java/java_generator_factory.cc new file mode 100644 index 0000000..ce71d43 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_generator_factory.cc @@ -0,0 +1,77 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: liujisi@google.com (Pherl Liu) + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +GeneratorFactory::GeneratorFactory() {} +GeneratorFactory::~GeneratorFactory() {} + +// =================================================================== + +ImmutableGeneratorFactory::ImmutableGeneratorFactory( + Context* context) : context_(context) { +} +ImmutableGeneratorFactory::~ImmutableGeneratorFactory() {} + +MessageGenerator* ImmutableGeneratorFactory::NewMessageGenerator( + const Descriptor* descriptor) const { + return new ImmutableMessageGenerator(descriptor, context_); +} + +ExtensionGenerator* ImmutableGeneratorFactory::NewExtensionGenerator( + const FieldDescriptor* descriptor) const { + return new ImmutableExtensionGenerator(descriptor, context_); +} + +ServiceGenerator* ImmutableGeneratorFactory::NewServiceGenerator( + const ServiceDescriptor* descriptor) const { + return new ImmutableServiceGenerator(descriptor, context_); +} + + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_generator_factory.h b/src/google/protobuf/compiler/java/java_generator_factory.h new file mode 100644 index 0000000..abf894f --- /dev/null +++ b/src/google/protobuf/compiler/java/java_generator_factory.h @@ -0,0 +1,101 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: liujisi@google.com (Pherl Liu) + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ + +#include + +namespace google { +namespace protobuf { + class FieldDescriptor; // descriptor.h + class Descriptor; // descriptor.h + class ServiceDescriptor; // descriptor.h + namespace compiler { + namespace java { + class MessageGenerator; // message.h + class ExtensionGenerator; // extension.h + class ServiceGenerator; // service.h + class Context; // context.h + } + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class GeneratorFactory { + public: + GeneratorFactory(); + virtual ~GeneratorFactory(); + + virtual MessageGenerator* NewMessageGenerator( + const Descriptor* descriptor) const = 0; + + virtual ExtensionGenerator* NewExtensionGenerator( + const FieldDescriptor* descriptor) const = 0; + + virtual ServiceGenerator* NewServiceGenerator( + const ServiceDescriptor* descriptor) const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorFactory); +}; + +// Factory that creates generators for immutable-default messages. +class ImmutableGeneratorFactory : public GeneratorFactory { + public: + ImmutableGeneratorFactory(Context* context); + virtual ~ImmutableGeneratorFactory(); + + virtual MessageGenerator* NewMessageGenerator( + const Descriptor* descriptor) const; + + virtual ExtensionGenerator* NewExtensionGenerator( + const FieldDescriptor* descriptor) const; + + virtual ServiceGenerator* NewServiceGenerator( + const ServiceDescriptor* descriptor) const; + + private: + Context* context_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableGeneratorFactory); +}; + + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index 7ed0c3c..fdd4e5e 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -32,11 +32,15 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include +#include #include #include #include +#include #include +#include #include #include @@ -45,6 +49,9 @@ namespace protobuf { namespace compiler { namespace java { +using internal::WireFormat; +using internal::WireFormatLite; + const char kThickSeparator[] = "// ===================================================================\n"; const char kThinSeparator[] = @@ -54,18 +61,47 @@ namespace { const char* kDefaultPackage = ""; -const string& FieldName(const FieldDescriptor* field) { +// Names that should be avoided as field names. +// Using them will cause the compiler to generate accessors whose names are +// colliding with methods defined in base classes. +const char* kForbiddenWordList[] = { + // message base class: + "cached_size", "serialized_size", + // java.lang.Object: + "class", +}; + +bool IsForbidden(const string& field_name) { + for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) { + if (field_name == kForbiddenWordList[i]) { + return true; + } + } + return false; +} + +string FieldName(const FieldDescriptor* field) { + string field_name; // Groups are hacky: The name of the field is just the lower-cased name // of the group type. In Java, though, we would like to retain the original // capitalization of the type name. if (GetType(field) == FieldDescriptor::TYPE_GROUP) { - return field->message_type()->name(); + field_name = field->message_type()->name(); } else { - return field->name(); + field_name = field->name(); } + if (IsForbidden(field_name)) { + // Append a trailing "#" to indicate that the name should be decorated to + // avoid collision with other names. + field_name += "#"; + } + return field_name; } -string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) { + +} // namespace + +string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { string result; // Note: I distrust ctype.h due to locales. for (int i = 0; i < input.size(); i++) { @@ -93,21 +129,27 @@ string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) { cap_next_letter = true; } } + // Add a trailing "_" if the name should be altered. + if (input[input.size() - 1] == '#') { + result += '_'; + } return result; } -} // namespace - string UnderscoresToCamelCase(const FieldDescriptor* field) { - return UnderscoresToCamelCaseImpl(FieldName(field), false); + return UnderscoresToCamelCase(FieldName(field), false); } string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { - return UnderscoresToCamelCaseImpl(FieldName(field), true); + return UnderscoresToCamelCase(FieldName(field), true); } string UnderscoresToCamelCase(const MethodDescriptor* method) { - return UnderscoresToCamelCaseImpl(method->name(), false); + return UnderscoresToCamelCase(method->name(), false); +} + +string UniqueFileScopeIdentifier(const Descriptor* descriptor) { + return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); } string StripProto(const string& filename) { @@ -118,35 +160,38 @@ string StripProto(const string& filename) { } } -string FileClassName(const FileDescriptor* file) { - if (file->options().has_java_outer_classname()) { - return file->options().java_outer_classname(); - } else { - string basename; - string::size_type last_slash = file->name().find_last_of('/'); - if (last_slash == string::npos) { - basename = file->name(); - } else { - basename = file->name().substr(last_slash + 1); - } - return UnderscoresToCamelCaseImpl(StripProto(basename), true); - } +string FileClassName(const FileDescriptor* file, bool immutable) { + ClassNameResolver name_resolver; + return name_resolver.GetFileClassName(file, immutable); } -string FileJavaPackage(const FileDescriptor* file) { +string FileJavaPackage(const FileDescriptor* file, bool immutable) { + string result; + if (file->options().has_java_package()) { - return file->options().java_package(); + result = file->options().java_package(); } else { - string result = kDefaultPackage; + result = kDefaultPackage; if (!file->package().empty()) { if (!result.empty()) result += '.'; result += file->package(); } - return result; } + + return result; +} + +string JavaPackageToDir(string package_name) { + string package_dir = + StringReplace(package_name, ".", "/", true); + if (!package_dir.empty()) package_dir += "/"; + return package_dir; } -string ToJavaName(const string& full_name, const FileDescriptor* file) { +// TODO(xiaofeng): This function is only kept for it's publicly referenced. +// It should be removed after mutable API up-integration. +string ToJavaName(const string& full_name, + const FileDescriptor* file) { string result; if (file->options().java_multiple_files()) { result = FileJavaPackage(file); @@ -166,11 +211,43 @@ string ToJavaName(const string& full_name, const FileDescriptor* file) { return result; } +string ClassName(const Descriptor* descriptor) { + ClassNameResolver name_resolver; + return name_resolver.GetClassName(descriptor, true); +} + +string ClassName(const EnumDescriptor* descriptor) { + ClassNameResolver name_resolver; + return name_resolver.GetClassName(descriptor, true); +} + +string ClassName(const ServiceDescriptor* descriptor) { + ClassNameResolver name_resolver; + return name_resolver.GetClassName(descriptor, true); +} + string ClassName(const FileDescriptor* descriptor) { - string result = FileJavaPackage(descriptor); - if (!result.empty()) result += '.'; - result += FileClassName(descriptor); - return result; + ClassNameResolver name_resolver; + return name_resolver.GetClassName(descriptor, true); +} + +string ExtraMessageInterfaces(const Descriptor* descriptor) { + string interfaces = "// @@protoc_insertion_point(message_implements:" + + descriptor->full_name() + ")"; + return interfaces; +} + + +string ExtraBuilderInterfaces(const Descriptor* descriptor) { + string interfaces = "// @@protoc_insertion_point(builder_implements:" + + descriptor->full_name() + ")"; + return interfaces; +} + +string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) { + string interfaces = "// @@protoc_insertion_point(interface_extends:" + + descriptor->full_name() + ")"; + return interfaces; } string FieldConstantName(const FieldDescriptor *field) { @@ -249,6 +326,35 @@ const char* BoxedPrimitiveTypeName(JavaType type) { return NULL; } +const char* FieldTypeName(FieldDescriptor::Type field_type) { + switch (field_type) { + case FieldDescriptor::TYPE_INT32 : return "INT32"; + case FieldDescriptor::TYPE_UINT32 : return "UINT32"; + case FieldDescriptor::TYPE_SINT32 : return "SINT32"; + case FieldDescriptor::TYPE_FIXED32 : return "FIXED32"; + case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32"; + case FieldDescriptor::TYPE_INT64 : return "INT64"; + case FieldDescriptor::TYPE_UINT64 : return "UINT64"; + case FieldDescriptor::TYPE_SINT64 : return "SINT64"; + case FieldDescriptor::TYPE_FIXED64 : return "FIXED64"; + case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64"; + case FieldDescriptor::TYPE_FLOAT : return "FLOAT"; + case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE"; + case FieldDescriptor::TYPE_BOOL : return "BOOL"; + case FieldDescriptor::TYPE_STRING : return "STRING"; + case FieldDescriptor::TYPE_BYTES : return "BYTES"; + case FieldDescriptor::TYPE_ENUM : return "ENUM"; + case FieldDescriptor::TYPE_GROUP : return "GROUP"; + case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE"; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + bool AllAscii(const string& text) { for (int i = 0; i < text.size(); i++) { if ((text[i] & 0x80) != 0) { @@ -258,7 +364,8 @@ bool AllAscii(const string& text) { return true; } -string DefaultValue(const FieldDescriptor* field) { +string DefaultValue(const FieldDescriptor* field, bool immutable, + ClassNameResolver* name_resolver) { // Switch on CppType since we need to know which default_value_* method // of FieldDescriptor to call. switch (field->cpp_type()) { @@ -315,17 +422,18 @@ string DefaultValue(const FieldDescriptor* field) { } else { // See comments in Internal.java for gory details. return strings::Substitute( - "com.google.protobuf.Internal.stringDefaultValue(\"$0\")", - CEscape(field->default_value_string())); + "com.google.protobuf.Internal.stringDefaultValue(\"$0\")", + CEscape(field->default_value_string())); } } case FieldDescriptor::CPPTYPE_ENUM: - return ClassName(field->enum_type()) + "." + - field->default_value_enum()->name(); + return name_resolver->GetClassName(field->enum_type(), immutable) + "." + + field->default_value_enum()->name(); case FieldDescriptor::CPPTYPE_MESSAGE: - return ClassName(field->message_type()) + ".getDefaultInstance()"; + return name_resolver->GetClassName(field->message_type(), immutable) + + ".getDefaultInstance()"; // No default because we want the compiler to complain if any new // types are added. @@ -335,6 +443,294 @@ string DefaultValue(const FieldDescriptor* field) { return ""; } +bool IsDefaultValueJavaDefault(const FieldDescriptor* field) { + // Switch on CppType since we need to know which default_value_* method + // of FieldDescriptor to call. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return field->default_value_int32() == 0; + case FieldDescriptor::CPPTYPE_UINT32: + return field->default_value_uint32() == 0; + case FieldDescriptor::CPPTYPE_INT64: + return field->default_value_int64() == 0L; + case FieldDescriptor::CPPTYPE_UINT64: + return field->default_value_uint64() == 0L; + case FieldDescriptor::CPPTYPE_DOUBLE: + return field->default_value_double() == 0.0; + case FieldDescriptor::CPPTYPE_FLOAT: + return field->default_value_float() == 0.0; + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() == false; + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + return false; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; +} + +const char* bit_masks[] = { + "0x00000001", + "0x00000002", + "0x00000004", + "0x00000008", + "0x00000010", + "0x00000020", + "0x00000040", + "0x00000080", + + "0x00000100", + "0x00000200", + "0x00000400", + "0x00000800", + "0x00001000", + "0x00002000", + "0x00004000", + "0x00008000", + + "0x00010000", + "0x00020000", + "0x00040000", + "0x00080000", + "0x00100000", + "0x00200000", + "0x00400000", + "0x00800000", + + "0x01000000", + "0x02000000", + "0x04000000", + "0x08000000", + "0x10000000", + "0x20000000", + "0x40000000", + "0x80000000", +}; + +string GetBitFieldName(int index) { + string varName = "bitField"; + varName += SimpleItoa(index); + varName += "_"; + return varName; +} + +string GetBitFieldNameForBit(int bitIndex) { + return GetBitFieldName(bitIndex / 32); +} + +namespace { + +string GenerateGetBitInternal(const string& prefix, int bitIndex) { + string varName = prefix + GetBitFieldNameForBit(bitIndex); + int bitInVarIndex = bitIndex % 32; + + string mask = bit_masks[bitInVarIndex]; + string result = "((" + varName + " & " + mask + ") == " + mask + ")"; + return result; +} + +string GenerateSetBitInternal(const string& prefix, int bitIndex) { + string varName = prefix + GetBitFieldNameForBit(bitIndex); + int bitInVarIndex = bitIndex % 32; + + string mask = bit_masks[bitInVarIndex]; + string result = varName + " |= " + mask; + return result; +} + +} // namespace + +string GenerateGetBit(int bitIndex) { + return GenerateGetBitInternal("", bitIndex); +} + +string GenerateSetBit(int bitIndex) { + return GenerateSetBitInternal("", bitIndex); +} + +string GenerateClearBit(int bitIndex) { + string varName = GetBitFieldNameForBit(bitIndex); + int bitInVarIndex = bitIndex % 32; + + string mask = bit_masks[bitInVarIndex]; + string result = varName + " = (" + varName + " & ~" + mask + ")"; + return result; +} + +string GenerateGetBitFromLocal(int bitIndex) { + return GenerateGetBitInternal("from_", bitIndex); +} + +string GenerateSetBitToLocal(int bitIndex) { + return GenerateSetBitInternal("to_", bitIndex); +} + +string GenerateGetBitMutableLocal(int bitIndex) { + return GenerateGetBitInternal("mutable_", bitIndex); +} + +string GenerateSetBitMutableLocal(int bitIndex) { + return GenerateSetBitInternal("mutable_", bitIndex); +} + +bool IsReferenceType(JavaType type) { + switch (type) { + case JAVATYPE_INT : return false; + case JAVATYPE_LONG : return false; + case JAVATYPE_FLOAT : return false; + case JAVATYPE_DOUBLE : return false; + case JAVATYPE_BOOLEAN: return false; + case JAVATYPE_STRING : return true; + case JAVATYPE_BYTES : return true; + case JAVATYPE_ENUM : return true; + case JAVATYPE_MESSAGE: return true; + + // No default because we want the compiler to complain if any new + // JavaTypes are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; +} + +const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) { + switch (GetType(field)) { + case FieldDescriptor::TYPE_INT32 : return "Int32"; + case FieldDescriptor::TYPE_UINT32 : return "UInt32"; + case FieldDescriptor::TYPE_SINT32 : return "SInt32"; + case FieldDescriptor::TYPE_FIXED32 : return "Fixed32"; + case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; + case FieldDescriptor::TYPE_INT64 : return "Int64"; + case FieldDescriptor::TYPE_UINT64 : return "UInt64"; + case FieldDescriptor::TYPE_SINT64 : return "SInt64"; + case FieldDescriptor::TYPE_FIXED64 : return "Fixed64"; + case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; + case FieldDescriptor::TYPE_FLOAT : return "Float"; + case FieldDescriptor::TYPE_DOUBLE : return "Double"; + case FieldDescriptor::TYPE_BOOL : return "Bool"; + case FieldDescriptor::TYPE_STRING : return "String"; + case FieldDescriptor::TYPE_BYTES : { + return "Bytes"; + } + case FieldDescriptor::TYPE_ENUM : return "Enum"; + case FieldDescriptor::TYPE_GROUP : return "Group"; + case FieldDescriptor::TYPE_MESSAGE : return "Message"; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +// For encodings with fixed sizes, returns that size in bytes. Otherwise +// returns -1. +int FixedSize(FieldDescriptor::Type type) { + switch (type) { + case FieldDescriptor::TYPE_INT32 : return -1; + case FieldDescriptor::TYPE_INT64 : return -1; + case FieldDescriptor::TYPE_UINT32 : return -1; + case FieldDescriptor::TYPE_UINT64 : return -1; + case FieldDescriptor::TYPE_SINT32 : return -1; + case FieldDescriptor::TYPE_SINT64 : return -1; + case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; + + case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; + case FieldDescriptor::TYPE_ENUM : return -1; + + case FieldDescriptor::TYPE_STRING : return -1; + case FieldDescriptor::TYPE_BYTES : return -1; + case FieldDescriptor::TYPE_GROUP : return -1; + case FieldDescriptor::TYPE_MESSAGE : return -1; + + // No default because we want the compiler to complain if any new + // types are added. + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return -1; +} + +// Sort the fields of the given Descriptor by number into a new[]'d array +// and return it. The caller should delete the returned array. +const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { + const FieldDescriptor** fields = + new const FieldDescriptor*[descriptor->field_count()]; + for (int i = 0; i < descriptor->field_count(); i++) { + fields[i] = descriptor->field(i); + } + sort(fields, fields + descriptor->field_count(), + FieldOrderingByNumber()); + return fields; +} + +// Returns true if the message type has any required fields. If it doesn't, +// we can optimize out calls to its isInitialized() method. +// +// already_seen is used to avoid checking the same type multiple times +// (and also to protect against recursion). +bool HasRequiredFields( + const Descriptor* type, + hash_set* already_seen) { + if (already_seen->count(type) > 0) { + // The type is already in cache. This means that either: + // a. The type has no required fields. + // b. We are in the midst of checking if the type has required fields, + // somewhere up the stack. In this case, we know that if the type + // has any required fields, they'll be found when we return to it, + // and the whole call to HasRequiredFields() will return true. + // Therefore, we don't have to check if this type has required fields + // here. + return false; + } + already_seen->insert(type); + + // If the type has extensions, an extension with message type could contain + // required fields, so we have to be conservative and assume such an + // extension exists. + if (type->extension_range_count() > 0) return true; + + for (int i = 0; i < type->field_count(); i++) { + const FieldDescriptor* field = type->field(i); + if (field->is_required()) { + return true; + } + if (GetJavaType(field) == JAVATYPE_MESSAGE) { + if (HasRequiredFields(field->message_type(), already_seen)) { + return true; + } + } + } + + return false; +} + +bool HasRequiredFields(const Descriptor* type) { + hash_set already_seen; + return HasRequiredFields(type, &already_seen); +} + +bool HasRepeatedFields(const Descriptor* descriptor) { + for (int i = 0; i < descriptor->field_count(); ++i) { + const FieldDescriptor* field = descriptor->field(i); + if (field->is_repeated()) { + return true; + } + } + return false; +} + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h index 3c8974c..6d1eae0 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -49,6 +49,9 @@ namespace java { extern const char kThickSeparator[]; extern const char kThinSeparator[]; +// Converts a name to camel-case. If cap_first_letter is true, capitalize the +// first letter. +string UnderscoresToCamelCase(const string& name, bool cap_first_letter); // Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes // "fooBarBaz" or "FooBarBaz", respectively. string UnderscoresToCamelCase(const FieldDescriptor* field); @@ -58,36 +61,70 @@ string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); // of lower-casing the first letter of the name.) string UnderscoresToCamelCase(const MethodDescriptor* method); +// Get an identifier that uniquely identifies this type within the file. +// This is used to declare static variables related to this type at the +// outermost file scope. +string UniqueFileScopeIdentifier(const Descriptor* descriptor); + // Strips ".proto" or ".protodevel" from the end of a filename. string StripProto(const string& filename); -// Gets the unqualified class name for the file. Each .proto file becomes a -// single Java class, with all its contents nested in that class. -string FileClassName(const FileDescriptor* file); +// Gets the unqualified class name for the file. For each .proto file, there +// will be one Java class containing all the immutable messages and another +// Java class containing all the mutable messages. +// TODO(xiaofeng): remove the default value after updating client code. +string FileClassName(const FileDescriptor* file, bool immutable = true); // Returns the file's Java package name. -string FileJavaPackage(const FileDescriptor* file); +string FileJavaPackage(const FileDescriptor* file, bool immutable = true); + +// Returns output directory for the given package name. +string JavaPackageToDir(string package_name); // Converts the given fully-qualified name in the proto namespace to its // fully-qualified name in the Java namespace, given that it is in the given // file. -string ToJavaName(const string& full_name, const FileDescriptor* file); +// TODO(xiaofeng): this method is deprecated and should be removed in the +// future. +string ToJavaName(const string& full_name, + const FileDescriptor* file); -// These return the fully-qualified class name corresponding to the given -// descriptor. -inline string ClassName(const Descriptor* descriptor) { - return ToJavaName(descriptor->full_name(), descriptor->file()); -} -inline string ClassName(const EnumDescriptor* descriptor) { - return ToJavaName(descriptor->full_name(), descriptor->file()); -} -inline string ClassName(const ServiceDescriptor* descriptor) { - return ToJavaName(descriptor->full_name(), descriptor->file()); +// TODO(xiaofeng): the following methods are kept for they are exposed +// publicly in //google/protobuf/compiler/java/names.h. They return +// immutable names only and should be removed after mutable API is +// integrated into google3. +string ClassName(const Descriptor* descriptor); +string ClassName(const EnumDescriptor* descriptor); +string ClassName(const ServiceDescriptor* descriptor); +string ClassName(const FileDescriptor* descriptor); + +// Comma-separate list of option-specified interfaces implemented by the +// Message, to follow the "implements" declaration of the Message definition. +string ExtraMessageInterfaces(const Descriptor* descriptor); +// Comma-separate list of option-specified interfaces implemented by the +// MutableMessage, to follow the "implements" declaration of the MutableMessage +// definition. +string ExtraMutableMessageInterfaces(const Descriptor* descriptor); +// Comma-separate list of option-specified interfaces implemented by the +// Builder, to follow the "implements" declaration of the Builder definition. +string ExtraBuilderInterfaces(const Descriptor* descriptor); +// Comma-separate list of option-specified interfaces extended by the +// MessageOrBuilder, to follow the "extends" declaration of the +// MessageOrBuilder definition. +string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor); + +// Get the unqualified Java class name for mutable messages. i.e. without +// package or outer classnames. +inline string ShortMutableJavaClassName(const Descriptor* descriptor) { + return descriptor->name(); } -inline string ExtensionIdentifierName(const FieldDescriptor* descriptor) { - return ToJavaName(descriptor->full_name(), descriptor->file()); + + +// Whether we should generate multiple java files for messages. +inline bool MultipleJavaFiles( + const FileDescriptor* descriptor, bool immutable) { + return descriptor->options().java_multiple_files(); } -string ClassName(const FileDescriptor* descriptor); // Get the unqualified name that should be used for a field's field // number constant. @@ -117,10 +154,23 @@ JavaType GetJavaType(const FieldDescriptor* field); // types. const char* BoxedPrimitiveTypeName(JavaType type); -string DefaultValue(const FieldDescriptor* field); +// Get the name of the java enum constant representing this type. E.g., +// "INT32" for FieldDescriptor::TYPE_INT32. The enum constant's full +// name is "com.google.protobuf.WireFormat.FieldType.INT32". +const char* FieldTypeName(const FieldDescriptor::Type field_type); -// Does this message class keep track of unknown fields? -inline bool HasUnknownFields(const Descriptor* descriptor) { +class ClassNameResolver; +string DefaultValue(const FieldDescriptor* field, bool immutable, + ClassNameResolver* name_resolver); +inline string ImmutableDefaultValue(const FieldDescriptor* field, + ClassNameResolver* name_resolver) { + return DefaultValue(field, true, name_resolver); +} +bool IsDefaultValueJavaDefault(const FieldDescriptor* field); + +// Does this message class use UnknownFieldSet? +// Otherwise, unknown fields will be stored in a ByteString object +inline bool UseUnknownFieldSet(const Descriptor* descriptor) { return descriptor->file()->options().optimize_for() != FileOptions::LITE_RUNTIME; } @@ -132,6 +182,11 @@ inline bool HasGeneratedMethods(const Descriptor* descriptor) { FileOptions::CODE_SIZE; } +// Does this message have specialized equals() and hashCode() methods? +inline bool HasEqualsAndHashCode(const Descriptor* descriptor) { + return descriptor->file()->options().java_generate_equals_and_hash(); +} + // Does this message class have descriptor and reflection methods? inline bool HasDescriptorMethods(const Descriptor* descriptor) { return descriptor->file()->options().optimize_for() != @@ -146,6 +201,12 @@ inline bool HasDescriptorMethods(const FileDescriptor* descriptor) { FileOptions::LITE_RUNTIME; } +inline bool HasNestedBuilders(const Descriptor* descriptor) { + // The proto-lite version doesn't support nested builders. + return descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} + // Should we generate generic services for this file? inline bool HasGenericServices(const FileDescriptor *file) { return file->service_count() > 0 && @@ -153,6 +214,106 @@ inline bool HasGenericServices(const FileDescriptor *file) { file->options().java_generic_services(); } +inline bool IsLazy(const FieldDescriptor* descriptor) { + // Currently, the proto-lite version suports lazy field. + // TODO(niwasaki): Support lazy fields also for other proto runtimes. + if (descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME) { + return false; + } + return descriptor->options().lazy(); +} + +// Methods for shared bitfields. + +// Gets the name of the shared bitfield for the given index. +string GetBitFieldName(int index); + +// Gets the name of the shared bitfield for the given bit index. +// Effectively, GetBitFieldName(bitIndex / 32) +string GetBitFieldNameForBit(int bitIndex); + +// Generates the java code for the expression that returns the boolean value +// of the bit of the shared bitfields for the given bit index. +// Example: "((bitField1_ & 0x04) == 0x04)" +string GenerateGetBit(int bitIndex); + +// Generates the java code for the expression that sets the bit of the shared +// bitfields for the given bit index. +// Example: "bitField1_ = (bitField1_ | 0x04)" +string GenerateSetBit(int bitIndex); + +// Generates the java code for the expression that clears the bit of the shared +// bitfields for the given bit index. +// Example: "bitField1_ = (bitField1_ & ~0x04)" +string GenerateClearBit(int bitIndex); + +// Does the same as GenerateGetBit but operates on the bit field on a local +// variable. This is used by the builder to copy the value in the builder to +// the message. +// Example: "((from_bitField1_ & 0x04) == 0x04)" +string GenerateGetBitFromLocal(int bitIndex); + +// Does the same as GenerateSetBit but operates on the bit field on a local +// variable. This is used by the builder to copy the value in the builder to +// the message. +// Example: "to_bitField1_ = (to_bitField1_ | 0x04)" +string GenerateSetBitToLocal(int bitIndex); + +// Does the same as GenerateGetBit but operates on the bit field on a local +// variable. This is used by the parsing constructor to record if a repeated +// field is mutable. +// Example: "((mutable_bitField1_ & 0x04) == 0x04)" +string GenerateGetBitMutableLocal(int bitIndex); + +// Does the same as GenerateSetBit but operates on the bit field on a local +// variable. This is used by the parsing constructor to record if a repeated +// field is mutable. +// Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)" +string GenerateSetBitMutableLocal(int bitIndex); + +// Returns whether the JavaType is a reference type. +bool IsReferenceType(JavaType type); + +// Returns the capitalized name for calling relative functions in +// CodedInputStream +const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable); + +// For encodings with fixed sizes, returns that size in bytes. Otherwise +// returns -1. +int FixedSize(FieldDescriptor::Type type); + +// Comparators used to sort fields in MessageGenerator +struct FieldOrderingByNumber { + inline bool operator()(const FieldDescriptor* a, + const FieldDescriptor* b) const { + return a->number() < b->number(); + } +}; + +struct ExtensionRangeOrdering { + bool operator()(const Descriptor::ExtensionRange* a, + const Descriptor::ExtensionRange* b) const { + return a->start < b->start; + } +}; + +// Sort the fields of the given Descriptor by number into a new[]'d array +// and return it. The caller should delete the returned array. +const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor); + +// Check a message type and its sub-message types recursively to see if any of +// them has a required field. Return true if a required field is found. +bool HasRequiredFields(const Descriptor* descriptor); + +// Whether a .proto file supports field presence test for non-message types. +inline bool SupportFieldPresence(const FileDescriptor* descriptor) { + return true; +} + +// Check whether a mesasge has repeated fields. +bool HasRepeatedFields(const Descriptor* descriptor); + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc new file mode 100644 index 0000000..32d97b6 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_lazy_message_field.cc @@ -0,0 +1,826 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: niwasaki@google.com (Naoki Iwasaki) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +ImmutableLazyMessageFieldGenerator:: +ImmutableLazyMessageFieldGenerator( + const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableMessageFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { +} + +ImmutableLazyMessageFieldGenerator::~ImmutableLazyMessageFieldGenerator() {} + +void ImmutableLazyMessageFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private com.google.protobuf.LazyFieldLite $name$_ =\n" + " new com.google.protobuf.LazyFieldLite();\n"); + + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" + "}\n"); + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " return $name$_;\n" + "}\n"); + } +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // When using nested-builders, the code initially works just like the + // non-nested builder case. It only creates a nested builder lazily on + // demand and then forever delegates to it after creation. + + printer->Print(variables_, + "private com.google.protobuf.LazyFieldLite $name$_ =\n" + " new com.google.protobuf.LazyFieldLite();\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" + "\n"); + } + + // The comments above the methods below are based on a hypothetical + // field of type "Field" called "Field". + + // boolean hasField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" + "}\n"); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "$name$_.setValue(value);\n" + "$on_changed$\n", + + NULL, // Lazy fields are supported only for lite-runtime. + + "$set_has_field_bit_builder$;\n" + "return this;\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "$name$_.setValue(builderForValue.build());\n" + "$on_changed$\n", + + NULL, + + "$set_has_field_bit_builder$;\n" + "return this;\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder merge$capitalized_name$($type$ value)", + + "if ($get_has_field_bit_builder$ &&\n" + " !$name$_.containsDefaultInstance()) {\n" + " $name$_.setValue(\n" + " $type$.newBuilder(\n" + " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" + "} else {\n" + " $name$_.setValue(value);\n" + "}\n" + "$on_changed$\n", + + NULL, + + "$set_has_field_bit_builder$;\n" + "return this;\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + "$name$_.clear();\n" + "$on_changed$\n", + + NULL, + + "$clear_has_field_bit_builder$;\n" + "return this;\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" + " $set_has_field_bit_builder$;\n" + " $on_changed$\n" + " return get$capitalized_name$FieldBuilder().getBuilder();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilder();\n" + " } else {\n" + " return $name$_;\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " $name$_,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); + } +} + + +void ImmutableLazyMessageFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.clear();\n"); +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.clear();\n"); + printer->Print(variables_, "$clear_has_field_bit_builder$;\n"); +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " $name$_.merge(other.$name$_);\n" + " $set_has_field_bit_builder$;\n" + "}\n"); +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); + + printer->Print(variables_, + "result.$name$_.setByteString(\n" + " $name$_.toByteString(),\n" + " $name$_.getExtensionRegistry());\n"); +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_.setByteString(input.readBytes(), extensionRegistry);\n"); + printer->Print(variables_, + "$set_has_field_bit_message$;\n"); +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + // Do not de-serialize lazy fields. + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " output.writeBytes($number$, $name$_.toByteString());\n" + "}\n"); +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeLazyFieldSize($number$, $name$_);\n" + "}\n"); +} + +// =================================================================== + +ImmutableLazyMessageOneofFieldGenerator:: +ImmutableLazyMessageOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableLazyMessageFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); + variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite"; +} + +ImmutableLazyMessageOneofFieldGenerator:: +~ImmutableLazyMessageOneofFieldGenerator() {} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" + " $type$.getDefaultInstance());\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); +} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // boolean hasField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" + " $type$.getDefaultInstance());\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + " $set_oneof_case_message$;\n" + "}\n" + "(($lazy_type$) $oneof_name$_).setValue(value);\n" + "$on_changed$\n", + + NULL, // Lazy fields are supported only for lite-runtime. + + "return this;\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + " $set_oneof_case_message$;\n" + "}\n" + "(($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n" + "$on_changed$\n", + + NULL, + + "return this;\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder merge$capitalized_name$($type$ value)", + + "if ($has_oneof_case_message$ &&\n" + " !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n" + " (($lazy_type$) $oneof_name$_).setValue(\n" + " $type$.newBuilder(\n" + " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" + "} else {\n" + " if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + " $set_oneof_case_message$;\n" + " }\n" + " (($lazy_type$) $oneof_name$_).setValue(value);\n" + "}\n" + "$on_changed$\n", + + NULL, + + "return this;\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + "if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + "}\n", + + NULL, + + "return this;\n"); +} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + "}\n" + "(($lazy_type$) $oneof_name$_).merge(\n" + " ($lazy_type$) other.$oneof_name$_);\n" + "$set_oneof_case_message$;\n"); +} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n"); + printer->Indent(); + + printer->Print(variables_, + "result.$oneof_name$_ = new $lazy_type$();\n" + "(($lazy_type$) result.$oneof_name$_).setByteString(\n" + " (($lazy_type$) $oneof_name$_).toByteString(),\n" + " (($lazy_type$) $oneof_name$_).getExtensionRegistry());\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + "}\n" + "(($lazy_type$) $oneof_name$_).setByteString(\n" + " input.readBytes(), extensionRegistry);\n" + "$set_oneof_case_message$;\n"); +} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + // Do not de-serialize lazy fields. + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.writeBytes(\n" + " $number$, (($lazy_type$) $oneof_name$_).toByteString());\n" + "}\n"); +} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n" + "}\n"); +} + +// =================================================================== + +RepeatedImmutableLazyMessageFieldGenerator:: +RepeatedImmutableLazyMessageFieldGenerator( + const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : RepeatedImmutableMessageFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { +} + + +RepeatedImmutableLazyMessageFieldGenerator:: +~RepeatedImmutableLazyMessageFieldGenerator() {} + +void RepeatedImmutableLazyMessageFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private java.util.List $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$>\n" + " get$capitalized_name$List() {\n" + " java.util.List<$type$> list =\n" + " new java.util.ArrayList<$type$>($name$_.size());\n" + " for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" + " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" + " }\n" + " return list;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List\n" + " get$capitalized_name$OrBuilderList() {\n" + " return get$capitalized_name$List();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return ($type$)\n" + " $name$_.get(index).getValue($type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" + " return ($type$OrBuilder)\n" + " $name$_.get(index).getValue($type$.getDefaultInstance());\n" + "}\n"); +} + +void RepeatedImmutableLazyMessageFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // When using nested-builders, the code initially works just like the + // non-nested builder case. It only creates a nested builder lazily on + // demand and then forever delegates to it after creation. + + printer->Print(variables_, + "private java.util.List $name$_ =\n" + " java.util.Collections.emptyList();\n" + + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ =\n" + " new java.util.ArrayList(\n" + " $name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n" + "\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" + "\n"); + } + + // The comments above the methods below are based on a hypothetical + // repeated field of type "Field" called "RepeatedField". + + // List getRepeatedFieldList() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List()", + + "java.util.List<$type$> list =\n" + " new java.util.ArrayList<$type$>($name$_.size());\n" + "for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" + " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" + "}\n" + "return java.util.Collections.unmodifiableList(list);\n", + + "return $name$Builder_.getMessageList();\n", + + NULL); + + // int getRepeatedFieldCount() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public int get$capitalized_name$Count()", + + "return $name$_.size();\n", + "return $name$Builder_.getCount();\n", + + NULL); + + // Field getRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public $type$ get$capitalized_name$(int index)", + + "return ($type$) $name$_.get(index).getValue(\n" + " $type$.getDefaultInstance());\n", + + "return $name$Builder_.getMessage(index);\n", + + NULL); + + // Builder setRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value)", + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" + "$on_changed$\n", + "$name$Builder_.setMessage(index, value);\n", + "return this;\n"); + + // Builder setRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n" + " builderForValue.build()));\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(index, builderForValue.build());\n", + + "return this;\n"); + + // Builder addRepeatedField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n" + + "$on_changed$\n", + + "$name$Builder_.addMessage(value);\n", + + "return this;\n"); + + // Builder addRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(index, value);\n", + + "return this;\n"); + + // Builder addRepeatedField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n" + " builderForValue.build()));\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(builderForValue.build());\n", + + "return this;\n"); + + // Builder addRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n" + " builderForValue.build()));\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(index, builderForValue.build());\n", + + "return this;\n"); + + // Builder addAllRepeatedField(Iterable values) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values)", + + "ensure$capitalized_name$IsMutable();\n" + "for (com.google.protobuf.MessageLite v : values) {\n" + " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n" + "}\n" + "$on_changed$\n", + + "$name$Builder_.addAllMessages(values);\n", + + "return this;\n"); + + // Builder clearAllRepeatedField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n" + "$on_changed$\n", + + "$name$Builder_.clear();\n", + + "return this;\n"); + + // Builder removeRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder remove$capitalized_name$(int index)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.remove(index);\n" + "$on_changed$\n", + + "$name$Builder_.remove(index);\n", + + "return this;\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" + " if ($name$Builder_ == null) {\n" + " return $name$_.get(index);" + " } else {\n" + " return $name$Builder_.getMessageOrBuilder(index);\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List \n" + " get$capitalized_name$OrBuilderList() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilderList();\n" + " } else {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " $type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " index, $type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$.Builder> \n" + " get$capitalized_name$BuilderList() {\n" + " return get$capitalized_name$FieldBuilder().getBuilderList();\n" + "}\n" + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " $name$_,\n" + " $get_mutable_bit_builder$,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); + } +} + +void RepeatedImmutableLazyMessageFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ =\n" + " new java.util.ArrayList();\n" + " $set_mutable_bit_parser$;\n" + "}\n" + "$name$_.add(new com.google.protobuf.LazyFieldLite(\n" + " extensionRegistry, input.readBytes()));\n"); +} + +void RepeatedImmutableLazyMessageFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeBytes($number$, $name$_.get(i).toByteString());\n" + "}\n"); +} + +void RepeatedImmutableLazyMessageFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeLazyFieldSize($number$, $name$_.get(i));\n" + "}\n"); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.h b/src/google/protobuf/compiler/java/java_lazy_message_field.h new file mode 100644 index 0000000..2a1f857 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_lazy_message_field.h @@ -0,0 +1,121 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: niwasaki@google.com (Naoki Iwasaki) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ + +#include +#include + +namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + } + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class ImmutableLazyMessageFieldGenerator + : public ImmutableMessageFieldGenerator { + public: + explicit ImmutableLazyMessageFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableLazyMessageFieldGenerator(); + + // overroads ImmutableMessageFieldGenerator --------------------------------- + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldGenerator); +}; + +class ImmutableLazyMessageOneofFieldGenerator + : public ImmutableLazyMessageFieldGenerator { + public: + ImmutableLazyMessageOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableLazyMessageOneofFieldGenerator(); + + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldGenerator); +}; + +class RepeatedImmutableLazyMessageFieldGenerator + : public RepeatedImmutableMessageFieldGenerator { + public: + explicit RepeatedImmutableLazyMessageFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~RepeatedImmutableLazyMessageFieldGenerator(); + + // overroads RepeatedImmutableMessageFieldGenerator ------------------------- + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index a326057..1cd08f7 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -32,17 +32,27 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include + #include #include -#include +#include +#include +#include + +#include +#include #include #include +#include #include -#include -#include +#include #include -#include +#include #include +#include +#include +#include namespace google { namespace protobuf { @@ -53,107 +63,31 @@ using internal::WireFormat; using internal::WireFormatLite; namespace { - -void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) { - // Print the field's proto-syntax definition as a comment. We don't want to - // print group bodies so we cut off after the first line. - string def = field->DebugString(); - printer->Print("// $def$\n", - "def", def.substr(0, def.find_first_of('\n'))); -} - -struct FieldOrderingByNumber { - inline bool operator()(const FieldDescriptor* a, - const FieldDescriptor* b) const { - return a->number() < b->number(); - } -}; - -struct ExtensionRangeOrdering { - bool operator()(const Descriptor::ExtensionRange* a, - const Descriptor::ExtensionRange* b) const { - return a->start < b->start; - } -}; - -// Sort the fields of the given Descriptor by number into a new[]'d array -// and return it. -const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { - const FieldDescriptor** fields = - new const FieldDescriptor*[descriptor->field_count()]; - for (int i = 0; i < descriptor->field_count(); i++) { - fields[i] = descriptor->field(i); - } - sort(fields, fields + descriptor->field_count(), - FieldOrderingByNumber()); - return fields; -} - -// Get an identifier that uniquely identifies this type within the file. -// This is used to declare static variables related to this type at the -// outermost file scope. -string UniqueFileScopeIdentifier(const Descriptor* descriptor) { - return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); -} - -// Returns true if the message type has any required fields. If it doesn't, -// we can optimize out calls to its isInitialized() method. -// -// already_seen is used to avoid checking the same type multiple times -// (and also to protect against recursion). -static bool HasRequiredFields( - const Descriptor* type, - hash_set* already_seen) { - if (already_seen->count(type) > 0) { - // The type is already in cache. This means that either: - // a. The type has no required fields. - // b. We are in the midst of checking if the type has required fields, - // somewhere up the stack. In this case, we know that if the type - // has any required fields, they'll be found when we return to it, - // and the whole call to HasRequiredFields() will return true. - // Therefore, we don't have to check if this type has required fields - // here. - return false; - } - already_seen->insert(type); - - // If the type has extensions, an extension with message type could contain - // required fields, so we have to be conservative and assume such an - // extension exists. - if (type->extension_range_count() > 0) return true; - - for (int i = 0; i < type->field_count(); i++) { - const FieldDescriptor* field = type->field(i); - if (field->is_required()) { - return true; - } - if (GetJavaType(field) == JAVATYPE_MESSAGE) { - if (HasRequiredFields(field->message_type(), already_seen)) { - return true; - } - } - } - - return false; -} - -static bool HasRequiredFields(const Descriptor* type) { - hash_set already_seen; - return HasRequiredFields(type, &already_seen); +bool GenerateHasBits(const Descriptor* descriptor) { + return SupportFieldPresence(descriptor->file()) || + HasRepeatedFields(descriptor); } - } // namespace // =================================================================== MessageGenerator::MessageGenerator(const Descriptor* descriptor) - : descriptor_(descriptor), - field_generators_(descriptor) { -} + : descriptor_(descriptor) {} MessageGenerator::~MessageGenerator() {} -void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { +// =================================================================== +// TODO(api): Move this class to a separate immutable_message.cc file. +ImmutableMessageGenerator::ImmutableMessageGenerator( + const Descriptor* descriptor, Context* context) + : MessageGenerator(descriptor), context_(context), + name_resolver_(context->GetNameResolver()), + field_generators_(descriptor, context_) { +} + +ImmutableMessageGenerator::~ImmutableMessageGenerator() {} + +void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is // used in the construction of descriptors, we have a tricky bootstrapping @@ -165,12 +99,12 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { map vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = ClassName(descriptor_); + vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); if (descriptor_->containing_type() != NULL) { vars["parent"] = UniqueFileScopeIdentifier( descriptor_->containing_type()); } - if (descriptor_->file()->options().java_multiple_files()) { + if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { // We can only make these package-private since the classes that use them // are in separate files. vars["private"] = ""; @@ -180,31 +114,28 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { // The descriptor for this type. printer->Print(vars, - "$private$static com.google.protobuf.Descriptors.Descriptor\n" + "$private$static final com.google.protobuf.Descriptors.Descriptor\n" " internal_$identifier$_descriptor;\n"); // And the FieldAccessorTable. - printer->Print(vars, - "$private$static\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" - " internal_$identifier$_fieldAccessorTable;\n"); + GenerateFieldAccessorTable(printer); } // Generate static members for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(descriptor_->nested_type(i)) + ImmutableMessageGenerator(descriptor_->nested_type(i), context_) .GenerateStaticVariables(printer); } } -void MessageGenerator::GenerateStaticVariableInitializers( +void ImmutableMessageGenerator::GenerateStaticVariableInitializers( io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { map vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = ClassName(descriptor_); + vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); if (descriptor_->containing_type() != NULL) { vars["parent"] = UniqueFileScopeIdentifier( descriptor_->containing_type()); @@ -222,82 +153,191 @@ void MessageGenerator::GenerateStaticVariableInitializers( } // And the FieldAccessorTable. - printer->Print(vars, - "internal_$identifier$_fieldAccessorTable = new\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" - " internal_$identifier$_descriptor,\n" - " new java.lang.String[] { "); - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print( - "\"$field_name$\", ", - "field_name", - UnderscoresToCapitalizedCamelCase(descriptor_->field(i))); - } - printer->Print("},\n" - " $classname$.class,\n" - " $classname$.Builder.class);\n", - "classname", ClassName(descriptor_)); + GenerateFieldAccessorTableInitializer(printer); } // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(descriptor_->nested_type(i)) + ImmutableMessageGenerator(descriptor_->nested_type(i), context_) .GenerateStaticVariableInitializers(printer); } +} + +void ImmutableMessageGenerator:: +GenerateFieldAccessorTable(io::Printer* printer) { + map vars; + vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); + if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { + // We can only make these package-private since the classes that use them + // are in separate files. + vars["private"] = ""; + } else { + vars["private"] = "private "; + } + printer->Print(vars, + "$private$static\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internal_$identifier$_fieldAccessorTable;\n"); +} - for (int i = 0; i < descriptor_->extension_count(); i++) { - // TODO(kenton): Reuse ExtensionGenerator objects? - ExtensionGenerator(descriptor_->extension(i)) - .GenerateInitializationCode(printer); +void ImmutableMessageGenerator:: +GenerateFieldAccessorTableInitializer(io::Printer* printer) { + printer->Print( + "internal_$identifier$_fieldAccessorTable = new\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" + " internal_$identifier$_descriptor,\n" + " new java.lang.String[] { ", + "identifier", + UniqueFileScopeIdentifier(descriptor_)); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + printer->Print( + "\"$field_name$\", ", + "field_name", info->capitalized_name); + } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof); + printer->Print( + "\"$oneof_name$\", ", + "oneof_name", info->capitalized_name); } + printer->Print("});\n"); } -void MessageGenerator::Generate(io::Printer* printer) { - bool is_own_file = - descriptor_->containing_type() == NULL && - descriptor_->file()->options().java_multiple_files(); +// =================================================================== +void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { if (HasDescriptorMethods(descriptor_)) { printer->Print( - "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" - " $classname$> {\n", - "static", is_own_file ? "" : "static", + "public interface $classname$OrBuilder extends\n" + " $extra_interfaces$\n" + " com.google.protobuf.GeneratedMessage.\n" + " ExtendableMessageOrBuilder<$classname$> {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } else { printer->Print( - "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" - " $classname$> {\n", - "static", is_own_file ? "" : "static", + "public interface $classname$OrBuilder extends \n" + " $extra_interfaces$\n" + " com.google.protobuf.GeneratedMessageLite.\n" + " ExtendableMessageOrBuilder<$classname$> {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } } else { if (HasDescriptorMethods(descriptor_)) { printer->Print( - "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage {\n", - "static", is_own_file ? "" : "static", + "public interface $classname$OrBuilder extends\n" + " $extra_interfaces$\n" + " com.google.protobuf.MessageOrBuilder {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } else { printer->Print( - "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessageLite {\n", - "static", is_own_file ? "" : "static", + "public interface $classname$OrBuilder extends\n" + " $extra_interfaces$\n" + " com.google.protobuf.MessageLiteOrBuilder {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } } + + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print("\n"); + field_generators_.get(descriptor_->field(i)) + .GenerateInterfaceMembers(printer); + } + printer->Outdent(); + + printer->Print("}\n"); +} + +// =================================================================== + +void ImmutableMessageGenerator::Generate(io::Printer* printer) { + bool is_own_file = + descriptor_->containing_type() == NULL && + MultipleJavaFiles(descriptor_->file(), /* immutable = */ true); + + WriteMessageDocComment(printer, descriptor_); + + // The builder_type stores the super type name of the nested Builder class. + string builder_type; + if (descriptor_->extension_range_count() > 0) { + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public$static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" + " $classname$> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "static", is_own_file ? " " : " static ", + "classname", descriptor_->name(), + "extra_interfaces", ExtraMessageInterfaces(descriptor_)); + builder_type = strings::Substitute( + "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>", + name_resolver_->GetImmutableClassName(descriptor_)); + } else { + printer->Print( + "public$static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" + " $classname$> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "static", is_own_file ? " " : " static ", + "classname", descriptor_->name(), + "extra_interfaces", ExtraMessageInterfaces(descriptor_)); + builder_type = strings::Substitute( + "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>", + name_resolver_->GetImmutableClassName(descriptor_)); + } + } else { + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public$static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "static", is_own_file ? " " : " static ", + "classname", descriptor_->name(), + "extra_interfaces", ExtraMessageInterfaces(descriptor_)); + builder_type = "com.google.protobuf.GeneratedMessage.Builder"; + } else { + printer->Print( + "public$static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "static", is_own_file ? " " : " static ", + "classname", descriptor_->name(), + "extra_interfaces", ExtraMessageInterfaces(descriptor_)); + builder_type = "com.google.protobuf.GeneratedMessageLite.Builder"; + } + } printer->Indent(); + // Using builder_type, instead of Builder, prevents the Builder class from + // being loaded into PermGen space when the default instance is created. + // This optimizes the PermGen space usage for clients that do not modify + // messages. printer->Print( "// Use $classname$.newBuilder() to construct.\n" - "private $classname$() {\n" - " initFields();\n" - "}\n" + "private $classname$($buildertype$ builder) {\n" + " super(builder);\n" + "$set_unknown_fields$\n" + "}\n", + "classname", descriptor_->name(), + "buildertype", builder_type, + "set_unknown_fields", + " this.unknownFields = builder.getUnknownFields();"); + printer->Print( // Used when constructing the default instance, which cannot be initialized // immediately because it may cyclically refer to other default instances. - "private $classname$(boolean noInit) {}\n" + "private $classname$(boolean noInit) {$set_default_unknown_fields$}\n" "\n" "private static final $classname$ defaultInstance;\n" "public static $classname$ getDefaultInstance() {\n" @@ -308,40 +348,131 @@ void MessageGenerator::Generate(io::Printer* printer) { " return defaultInstance;\n" "}\n" "\n", - "classname", descriptor_->name()); + "classname", descriptor_->name(), + "set_default_unknown_fields", UseUnknownFieldSet(descriptor_) + ? " this.unknownFields =" + " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); " + : " this.unknownFields = com.google.protobuf.ByteString.EMPTY;"); - if (HasDescriptorMethods(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { printer->Print( - "public static final com.google.protobuf.Descriptors.Descriptor\n" - " getDescriptor() {\n" - " return $fileclass$.internal_$identifier$_descriptor;\n" - "}\n" - "\n" - "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" - " internalGetFieldAccessorTable() {\n" - " return $fileclass$.internal_$identifier$_fieldAccessorTable;\n" - "}\n" - "\n", - "fileclass", ClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); + "private final com.google.protobuf.UnknownFieldSet unknownFields;\n" + "" + "@java.lang.Override\n" + "public final com.google.protobuf.UnknownFieldSet\n" + " getUnknownFields() {\n" + " return this.unknownFields;\n" + "}\n"); + } else { + printer->Print( + "private final com.google.protobuf.ByteString unknownFields;\n"); + } + + if (HasGeneratedMethods(descriptor_)) { + GenerateParsingConstructor(printer); } - // Nested types and extensions + GenerateDescriptorMethods(printer); + GenerateParser(printer); + + // Nested types for (int i = 0; i < descriptor_->enum_type_count(); i++) { - EnumGenerator(descriptor_->enum_type(i)).Generate(printer); + EnumGenerator(descriptor_->enum_type(i), true, context_) + .Generate(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator(descriptor_->nested_type(i)).Generate(printer); + ImmutableMessageGenerator messageGenerator( + descriptor_->nested_type(i), context_); + messageGenerator.GenerateInterface(printer); + messageGenerator.Generate(printer); } - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator(descriptor_->extension(i)).Generate(printer); + if (GenerateHasBits(descriptor_)) { + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += field_generators_.get(descriptor_->field(i)) + .GetNumBitsForMessage(); + } + int totalInts = (totalBits + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + } + + // oneof + map vars; + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + vars["oneof_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name; + vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name; + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + // oneofCase_ and oneof_ + printer->Print(vars, + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); + // OneofCase enum + printer->Print(vars, + "public enum $oneof_capitalized_name$Case\n" + " implements com.google.protobuf.Internal.EnumLite {\n"); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "$field_name$($field_number$),\n", + "field_name", + ToUpper(field->name()), + "field_number", + SimpleItoa(field->number())); + } + printer->Print( + "$cap_oneof_name$_NOT_SET(0);\n", + "cap_oneof_name", + ToUpper(vars["oneof_name"])); + printer->Print(vars, + "private int value = 0;\n" + "private $oneof_capitalized_name$Case(int value) {\n" + " this.value = value;\n" + "}\n"); + printer->Print(vars, + "public static $oneof_capitalized_name$Case valueOf(int value) {\n" + " switch (value) {\n"); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + " case $field_number$: return $field_name$;\n", + "field_number", + SimpleItoa(field->number()), + "field_name", + ToUpper(field->name())); + } + printer->Print( + " case 0: return $cap_oneof_name$_NOT_SET;\n" + " default: throw new java.lang.IllegalArgumentException(\n" + " \"Value is undefined for this oneof enum.\");\n" + " }\n" + "}\n" + "public int getNumber() {\n" + " return this.value;\n" + "}\n", + "cap_oneof_name", ToUpper(vars["oneof_name"])); + printer->Outdent(); + printer->Print("};\n\n"); + // oneofCase() + printer->Print(vars, + "public $oneof_capitalized_name$Case\n" + "get$oneof_capitalized_name$Case() {\n" + " return $oneof_capitalized_name$Case.valueOf(\n" + " $oneof_name$Case_);\n" + "}\n" + "\n"); } // Fields for (int i = 0; i < descriptor_->field_count(); i++) { - PrintFieldComment(printer, descriptor_->field(i)); printer->Print("public static final int $constant_name$ = $number$;\n", "constant_name", FieldConstantName(descriptor_->field(i)), "number", SimpleItoa(descriptor_->field(i)->number())); @@ -354,48 +485,60 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print("private void initFields() {\n"); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateInitializationCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateInitializationCode(printer); + } } + printer->Outdent(); printer->Print("}\n"); if (HasGeneratedMethods(descriptor_)) { - GenerateIsInitialized(printer); + GenerateIsInitialized(printer, MEMOIZE); GenerateMessageSerializationMethods(printer); } + if (HasEqualsAndHashCode(descriptor_)) { + GenerateEqualsAndHashCode(printer); + } + + GenerateParseFromMethods(printer); GenerateBuilder(printer); - // Force initialization of outer class. Otherwise, nested extensions may - // not be initialized. Also carefully initialize the default instance in - // such a way that it doesn't conflict with other initialization. + // Carefully initialize the default instance in such a way that it doesn't + // conflict with other initialization. printer->Print( "\n" "static {\n" " defaultInstance = new $classname$(true);\n" - " $file$.internalForceInit();\n" " defaultInstance.initFields();\n" - "}\n", - "file", ClassName(descriptor_->file()), - "classname", descriptor_->name()); - - printer->Print( + "}\n" "\n" "// @@protoc_insertion_point(class_scope:$full_name$)\n", + "classname", descriptor_->name(), "full_name", descriptor_->full_name()); + // Extensions must be declared after the defaultInstance is initialized + // because the defaultInstance is used by the extension to lazily retrieve + // the outer class's FileDescriptor. + for (int i = 0; i < descriptor_->extension_count(); i++) { + ImmutableExtensionGenerator(descriptor_->extension(i), context_) + .Generate(printer); + } + printer->Outdent(); printer->Print("}\n\n"); } + // =================================================================== -void MessageGenerator:: +void ImmutableMessageGenerator:: GenerateMessageSerializationMethods(io::Printer* printer) { scoped_array sorted_fields( - SortFieldsByNumber(descriptor_)); + SortFieldsByNumber(descriptor_)); vector sorted_extensions; for (int i = 0; i < descriptor_->extension_range_count(); ++i) { @@ -420,15 +563,18 @@ GenerateMessageSerializationMethods(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { printer->Print( - "com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage\n" - " .ExtensionWriter extensionWriter =\n" + "com.google.protobuf.GeneratedMessage$lite$\n" + " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" " newMessageSetExtensionWriter();\n", - "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite"); + "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } else { printer->Print( - "com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage\n" - " .ExtensionWriter extensionWriter = newExtensionWriter();\n", - "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite"); + "com.google.protobuf.GeneratedMessage$lite$\n" + " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" + " newExtensionWriter();\n", + "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } } @@ -447,7 +593,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } } - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { if (descriptor_->options().message_set_wire_format()) { printer->Print( "getUnknownFields().writeAsMessageSetTo(output);\n"); @@ -455,6 +601,9 @@ GenerateMessageSerializationMethods(io::Printer* printer) { printer->Print( "getUnknownFields().writeTo(output);\n"); } + } else { + printer->Print( + "output.writeRawBytes(unknownFields);\n"); } printer->Outdent(); @@ -483,7 +632,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } } - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { if (descriptor_->options().message_set_wire_format()) { printer->Print( "size += getUnknownFields().getSerializedSizeAsMessageSet();\n"); @@ -491,6 +640,9 @@ GenerateMessageSerializationMethods(io::Printer* printer) { printer->Print( "size += getUnknownFields().getSerializedSize();\n"); } + } else { + printer->Print( + "size += unknownFields.size();\n"); } printer->Outdent(); @@ -499,9 +651,18 @@ GenerateMessageSerializationMethods(io::Printer* printer) { " return size;\n" "}\n" "\n"); + + printer->Print( + "private static final long serialVersionUID = 0L;\n" + "@java.lang.Override\n" + "protected java.lang.Object writeReplace()\n" + " throws java.io.ObjectStreamException {\n" + " return super.writeReplace();\n" + "}\n" + "\n"); } -void MessageGenerator:: +void ImmutableMessageGenerator:: GenerateParseFromMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized @@ -510,79 +671,65 @@ GenerateParseFromMethods(io::Printer* printer) { "public static $classname$ parseFrom(\n" " com.google.protobuf.ByteString data)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return newBuilder().mergeFrom(data).buildParsed();\n" + " return PARSER.parseFrom(data);\n" "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.ByteString data,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return newBuilder().mergeFrom(data, extensionRegistry)\n" - " .buildParsed();\n" + " return PARSER.parseFrom(data, extensionRegistry);\n" "}\n" "public static $classname$ parseFrom(byte[] data)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return newBuilder().mergeFrom(data).buildParsed();\n" + " return PARSER.parseFrom(data);\n" "}\n" "public static $classname$ parseFrom(\n" " byte[] data,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return newBuilder().mergeFrom(data, extensionRegistry)\n" - " .buildParsed();\n" + " return PARSER.parseFrom(data, extensionRegistry);\n" "}\n" "public static $classname$ parseFrom(java.io.InputStream input)\n" " throws java.io.IOException {\n" - " return newBuilder().mergeFrom(input).buildParsed();\n" + " return PARSER.parseFrom(input);\n" "}\n" "public static $classname$ parseFrom(\n" " java.io.InputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " return newBuilder().mergeFrom(input, extensionRegistry)\n" - " .buildParsed();\n" + " return PARSER.parseFrom(input, extensionRegistry);\n" "}\n" "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n" " throws java.io.IOException {\n" - " Builder builder = newBuilder();\n" - " if (builder.mergeDelimitedFrom(input)) {\n" - " return builder.buildParsed();\n" - " } else {\n" - " return null;\n" - " }\n" + " return PARSER.parseDelimitedFrom(input);\n" "}\n" "public static $classname$ parseDelimitedFrom(\n" " java.io.InputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " Builder builder = newBuilder();\n" - " if (builder.mergeDelimitedFrom(input, extensionRegistry)) {\n" - " return builder.buildParsed();\n" - " } else {\n" - " return null;\n" - " }\n" + " return PARSER.parseDelimitedFrom(input, extensionRegistry);\n" "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.CodedInputStream input)\n" " throws java.io.IOException {\n" - " return newBuilder().mergeFrom(input).buildParsed();\n" + " return PARSER.parseFrom(input);\n" "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.CodedInputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " return newBuilder().mergeFrom(input, extensionRegistry)\n" - " .buildParsed();\n" + " return PARSER.parseFrom(input, extensionRegistry);\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } -void MessageGenerator::GenerateSerializeOneField( +void ImmutableMessageGenerator::GenerateSerializeOneField( io::Printer* printer, const FieldDescriptor* field) { field_generators_.get(field).GenerateSerializationCode(printer); } -void MessageGenerator::GenerateSerializeOneExtensionRange( +void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( io::Printer* printer, const Descriptor::ExtensionRange* range) { printer->Print( "extensionWriter.writeUntil($end$, output);\n", @@ -591,7 +738,7 @@ void MessageGenerator::GenerateSerializeOneExtensionRange( // =================================================================== -void MessageGenerator::GenerateBuilder(io::Printer* printer) { +void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( "public static Builder newBuilder() { return Builder.create(); }\n" "public Builder newBuilderForType() { return newBuilder(); }\n" @@ -600,47 +747,119 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { "}\n" "public Builder toBuilder() { return newBuilder(this); }\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + if (HasNestedBuilders(descriptor_)) { + printer->Print( + "@java.lang.Override\n" + "protected Builder newBuilderForType(\n" + " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" + " Builder builder = new Builder(parent);\n" + " return builder;\n" + "}\n"); + } + + WriteMessageDocComment(printer, descriptor_); if (descriptor_->extension_range_count() > 0) { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" - " $classname$, Builder> {\n", - "classname", ClassName(descriptor_)); + " $classname$, Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } else { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n" - " $classname$, Builder> {\n", - "classname", ClassName(descriptor_)); + " $classname$, Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } } else { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.Builder {\n", - "classname", ClassName(descriptor_)); + " com.google.protobuf.GeneratedMessage.Builder implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } else { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessageLite.Builder<\n" - " $classname$, Builder> {\n", - "classname", ClassName(descriptor_)); + " $classname$, Builder>\n" + " implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } } printer->Indent(); + GenerateDescriptorMethods(printer); GenerateCommonBuilderMethods(printer); if (HasGeneratedMethods(descriptor_)) { + GenerateIsInitialized(printer, DONT_MEMOIZE); GenerateBuilderParsingMethods(printer); } + // oneof + map vars; + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + vars["oneof_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name; + vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name; + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + // oneofCase_ and oneof_ + printer->Print(vars, + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); + // oneofCase() and clearOneof() + printer->Print(vars, + "public $oneof_capitalized_name$Case\n" + " get$oneof_capitalized_name$Case() {\n" + " return $oneof_capitalized_name$Case.valueOf(\n" + " $oneof_name$Case_);\n" + "}\n" + "\n" + "public Builder clear$oneof_capitalized_name$() {\n" + " $oneof_name$Case_ = 0;\n" + " $oneof_name$_ = null;\n"); + if (HasDescriptorMethods(descriptor_)) { + printer->Print(" onChanged();\n"); + } + printer->Print( + " return this;\n" + "}\n" + "\n"); + } + + if (GenerateHasBits(descriptor_)) { + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += field_generators_.get(descriptor_->field(i)) + .GetNumBitsForBuilder(); + } + int totalInts = (totalBits + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + } + for (int i = 0; i < descriptor_->field_count(); i++) { printer->Print("\n"); - PrintFieldComment(printer, descriptor_->field(i)); field_generators_.get(descriptor_->field(i)) .GenerateBuilderMembers(printer); } @@ -654,98 +873,209 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print("}\n"); } +void ImmutableMessageGenerator:: +GenerateDescriptorMethods(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_)) { + if (!descriptor_->options().no_standard_descriptor_accessor()) { + printer->Print( + "public static final com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptor() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" + "}\n" + "\n", + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); + } + printer->Print( + "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internalGetFieldAccessorTable() {\n" + " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" + " .ensureFieldAccessorsInitialized(\n" + " $classname$.class, $classname$.Builder.class);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); + } +} + // =================================================================== -void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { +void ImmutableMessageGenerator:: +GenerateCommonBuilderMethods(io::Printer* printer) { printer->Print( - "private $classname$ result;\n" - "\n" "// Construct using $classname$.newBuilder()\n" - "private Builder() {}\n" - "\n" - "private static Builder create() {\n" - " Builder builder = new Builder();\n" - " builder.result = new $classname$();\n" - " return builder;\n" + "private Builder() {\n" + " maybeForceBuilderInitialization();\n" "}\n" - "\n" - "protected $classname$ internalGetResult() {\n" - " return result;\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "private Builder(\n" + " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" + " super(parent);\n" + " maybeForceBuilderInitialization();\n" + "}\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } + + + if (HasNestedBuilders(descriptor_)) { + printer->Print( + "private void maybeForceBuilderInitialization() {\n" + " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n"); + + printer->Indent(); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateFieldBuilderInitializationCode(printer); + } + } + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + "}\n"); + } else { + printer->Print( + "private void maybeForceBuilderInitialization() {\n" + "}\n"); + } + + printer->Print( + "private static Builder create() {\n" + " return new Builder();\n" "}\n" "\n" "public Builder clear() {\n" - " if (result == null) {\n" - " throw new IllegalStateException(\n" - " \"Cannot call clear() after build().\");\n" - " }\n" - " result = new $classname$();\n" + " super.clear();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateBuilderClearCode(printer); + } + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "$oneof_name$Case_ = 0;\n" + "$oneof_name$_ = null;\n", + "oneof_name", context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name); + } + + printer->Outdent(); + + printer->Print( " return this;\n" "}\n" "\n" "public Builder clone() {\n" - " return create().mergeFrom(result);\n" + " return create().mergeFrom(buildPartial());\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); if (HasDescriptorMethods(descriptor_)) { printer->Print( "public com.google.protobuf.Descriptors.Descriptor\n" " getDescriptorForType() {\n" - " return $classname$.getDescriptor();\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); } printer->Print( "public $classname$ getDefaultInstanceForType() {\n" " return $classname$.getDefaultInstance();\n" "}\n" - "\n" - "public boolean isInitialized() {\n" - " return result.isInitialized();\n" - "}\n", - "classname", ClassName(descriptor_)); + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); // ----------------------------------------------------------------- printer->Print( "public $classname$ build() {\n" - // If result == null, we'll throw an appropriate exception later. - " if (result != null && !isInitialized()) {\n" + " $classname$ result = buildPartial();\n" + " if (!result.isInitialized()) {\n" " throw newUninitializedMessageException(result);\n" " }\n" - " return buildPartial();\n" - "}\n" - "\n" - "private $classname$ buildParsed()\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " if (!isInitialized()) {\n" - " throw newUninitializedMessageException(\n" - " result).asInvalidProtocolBufferException();\n" - " }\n" - " return buildPartial();\n" + " return result;\n" "}\n" "\n" "public $classname$ buildPartial() {\n" - " if (result == null) {\n" - " throw new IllegalStateException(\n" - " \"build() has already been called on this Builder.\");\n" - " }\n", - "classname", ClassName(descriptor_)); + " $classname$ result = new $classname$(this);\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + printer->Indent(); + int totalBuilderBits = 0; + int totalMessageBits = 0; for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer); + const ImmutableFieldGenerator& field = + field_generators_.get(descriptor_->field(i)); + totalBuilderBits += field.GetNumBitsForBuilder(); + totalMessageBits += field.GetNumBitsForMessage(); } - + int totalBuilderInts = (totalBuilderBits + 31) / 32; + int totalMessageInts = (totalMessageBits + 31) / 32; + + if (GenerateHasBits(descriptor_)) { + // Local vars for from and to bit fields to avoid accessing the builder and + // message over and over for these fields. Seems to provide a slight + // perforamance improvement in micro benchmark and this is also what proto1 + // code does. + for (int i = 0; i < totalBuilderInts; i++) { + printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + for (int i = 0; i < totalMessageInts; i++) { + printer->Print("int to_$bit_field_name$ = 0;\n", + "bit_field_name", GetBitFieldName(i)); + } + } + + // Output generation code for each field. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer); + } + + if (GenerateHasBits(descriptor_)) { + // Copy the bit field results to the generated message + for (int i = 0; i < totalMessageInts; i++) { + printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n", + "oneof_name", context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name); + } + printer->Outdent(); + + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + " onBuilt();\n"); + } + printer->Print( - " $classname$ returnMe = result;\n" - " result = null;\n" - " return returnMe;\n" + " return result;\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); // ----------------------------------------------------------------- @@ -763,7 +1093,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " }\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } printer->Print( @@ -771,11 +1101,48 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { // Optimization: If other is the default instance, we know none of its // fields are set so we can skip the merge. " if (other == $classname$.getDefaultInstance()) return this;\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)).GenerateMergingCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get( + descriptor_->field(i)).GenerateMergingCode(printer); + } + } + + // Merge oneof fields. + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + printer->Print( + "switch (other.get$oneof_capitalized_name$Case()) {\n", + "oneof_capitalized_name", + context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "case $field_name$: {\n", + "field_name", + ToUpper(field->name())); + printer->Indent(); + field_generators_.get(field).GenerateMergingCode(printer); + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name)); + printer->Outdent(); + printer->Print( + "}\n"); } printer->Outdent(); @@ -786,9 +1153,13 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " this.mergeExtensionFields(other);\n"); } - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { printer->Print( " this.mergeUnknownFields(other.getUnknownFields());\n"); + } else { + printer->Print( + " setUnknownFields(\n" + " getUnknownFields().concat(other.unknownFields));\n"); } printer->Print( @@ -800,58 +1171,359 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { // =================================================================== -void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { - scoped_array sorted_fields( - SortFieldsByNumber(descriptor_)); - +void ImmutableMessageGenerator:: +GenerateBuilderParsingMethods(io::Printer* printer) { printer->Print( "public Builder mergeFrom(\n" " com.google.protobuf.CodedInputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws java.io.IOException {\n"); + " throws java.io.IOException {\n" + " $classname$ parsedMessage = null;\n" + " try {\n" + " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n" + " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" + " parsedMessage = ($classname$) e.getUnfinishedMessage();\n" + " throw e;\n" + " } finally {\n" + " if (parsedMessage != null) {\n" + " mergeFrom(parsedMessage);\n" + " }\n" + " }\n" + " return this;\n" + "}\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); +} + +// =================================================================== + +void ImmutableMessageGenerator::GenerateIsInitialized( + io::Printer* printer, UseMemoization useMemoization) { + bool memoization = useMemoization == MEMOIZE; + if (memoization) { + // Memoizes whether the protocol buffer is fully initialized (has all + // required fields). -1 means not yet computed. 0 means false and 1 means + // true. + printer->Print( + "private byte memoizedIsInitialized = -1;\n"); + } + printer->Print( + "public final boolean isInitialized() {\n"); printer->Indent(); - if (HasUnknownFields(descriptor_)) { + if (memoization) { + // Don't directly compare to -1 to avoid an Android x86 JIT bug. printer->Print( - "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" - " com.google.protobuf.UnknownFieldSet.newBuilder(\n" - " this.getUnknownFields());\n"); + "byte isInitialized = memoizedIsInitialized;\n" + "if (isInitialized == 1) return true;\n" + "if (isInitialized == 0) return false;\n" + "\n"); + } + + // Check that all required fields in this message are set. + // TODO(kenton): We can optimize this when we switch to putting all the + // "has" fields into a single bitfield. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + + if (field->is_required()) { + printer->Print( + "if (!has$name$()) {\n" + " $memoize$\n" + " return false;\n" + "}\n", + "name", info->capitalized_name, + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + } } + // Now check that all embedded messages are initialized. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + if (GetJavaType(field) == JAVATYPE_MESSAGE && + HasRequiredFields(field->message_type())) { + switch (field->label()) { + case FieldDescriptor::LABEL_REQUIRED: + printer->Print( + "if (!get$name$().isInitialized()) {\n" + " $memoize$\n" + " return false;\n" + "}\n", + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name, + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + break; + case FieldDescriptor::LABEL_OPTIONAL: + printer->Print( + "if (has$name$()) {\n" + " if (!get$name$().isInitialized()) {\n" + " $memoize$\n" + " return false;\n" + " }\n" + "}\n", + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name, + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + break; + case FieldDescriptor::LABEL_REPEATED: + printer->Print( + "for (int i = 0; i < get$name$Count(); i++) {\n" + " if (!get$name$(i).isInitialized()) {\n" + " $memoize$\n" + " return false;\n" + " }\n" + "}\n", + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name, + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + break; + } + } + } + + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "if (!extensionsAreInitialized()) {\n" + " $memoize$\n" + " return false;\n" + "}\n", + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + } + + printer->Outdent(); + + if (memoization) { + printer->Print( + " memoizedIsInitialized = 1;\n"); + } + + printer->Print( + " return true;\n" + "}\n" + "\n"); +} + +// =================================================================== + +namespace { +bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) { + if (field->is_repeated()) { + return false; + } + if (SupportFieldPresence(field->file())) { + return true; + } + return GetJavaType(field) == JAVATYPE_MESSAGE && + field->containing_oneof() == NULL; +} +} // namespace + +void ImmutableMessageGenerator:: +GenerateEqualsAndHashCode(io::Printer* printer) { printer->Print( - "while (true) {\n"); + "@java.lang.Override\n" + "public boolean equals(final java.lang.Object obj) {\n"); printer->Indent(); + printer->Print( + "if (obj == this) {\n" + " return true;\n" + "}\n" + "if (!(obj instanceof $classname$)) {\n" + " return super.equals(obj);\n" + "}\n" + "$classname$ other = ($classname$) obj;\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Print("boolean result = true;\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); + if (check_has_bits) { + printer->Print( + "result = result && (has$name$() == other.has$name$());\n" + "if (has$name$()) {\n", + "name", info->capitalized_name); + printer->Indent(); + } + field_generators_.get(field).GenerateEqualsCode(printer); + if (check_has_bits) { + printer->Outdent(); + printer->Print( + "}\n"); + } + } + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "result = result &&\n" + " getUnknownFields().equals(other.getUnknownFields());\n"); + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "result = result &&\n" + " getExtensionFields().equals(other.getExtensionFields());\n"); + } + } + printer->Print( + "return result;\n"); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); printer->Print( - "int tag = input.readTag();\n" - "switch (tag) {\n"); + "@java.lang.Override\n" + "public int hashCode() {\n"); + printer->Indent(); + printer->Print( + "if (memoizedHashCode != 0) {\n"); + printer->Indent(); + printer->Print( + "return memoizedHashCode;\n"); + printer->Outdent(); + printer->Print( + "}\n" + "int hash = 41;\n"); + + if (HasDescriptorMethods(descriptor_)) { + printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n"); + } else { + // Include the hash of the class so that two objects with different types + // but the same field values will probably have different hashes. + printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); + if (check_has_bits) { + printer->Print( + "if (has$name$()) {\n", + "name", info->capitalized_name); + printer->Indent(); + } + field_generators_.get(field).GenerateHashCode(printer); + if (check_has_bits) { + printer->Outdent(); + printer->Print("}\n"); + } + } + if (HasDescriptorMethods(descriptor_)) { + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "hash = hashFields(hash, getExtensionFields());\n"); + } + } + + if (UseUnknownFieldSet(descriptor_)) { + printer->Print( + "hash = (29 * hash) + getUnknownFields().hashCode();\n"); + } else { + printer->Print( + "hash = (29 * hash) + unknownFields.hashCode();\n"); + } + printer->Print( + "memoizedHashCode = hash;\n" + "return hash;\n"); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); +} + +// =================================================================== + +void ImmutableMessageGenerator:: +GenerateExtensionRegistrationCode(io::Printer* printer) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + ImmutableExtensionGenerator(descriptor_->extension(i), context_) + .GenerateRegistrationCode(printer); + } + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + ImmutableMessageGenerator(descriptor_->nested_type(i), context_) + .GenerateExtensionRegistrationCode(printer); + } +} + +// =================================================================== +void ImmutableMessageGenerator:: +GenerateParsingConstructor(io::Printer* printer) { + scoped_array sorted_fields( + SortFieldsByNumber(descriptor_)); + + printer->Print( + "private $classname$(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n", + "classname", descriptor_->name()); printer->Indent(); - if (HasUnknownFields(descriptor_)) { + // Initialize all fields to default. + printer->Print( + "initFields();\n"); + + // Use builder bits to track mutable repeated fields. + int totalBuilderBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + const ImmutableFieldGenerator& field = + field_generators_.get(descriptor_->field(i)); + totalBuilderBits += field.GetNumBitsForBuilder(); + } + int totalBuilderInts = (totalBuilderBits + 31) / 32; + for (int i = 0; i < totalBuilderInts; i++) { + printer->Print("int mutable_$bit_field_name$ = 0;\n", + "bit_field_name", GetBitFieldName(i)); + } + + if (UseUnknownFieldSet(descriptor_)) { printer->Print( - "case 0:\n" // zero signals EOF / limit reached - " this.setUnknownFields(unknownFields.build());\n" - " return this;\n" - "default: {\n" - " if (!parseUnknownField(input, unknownFields,\n" - " extensionRegistry, tag)) {\n" - " this.setUnknownFields(unknownFields.build());\n" - " return this;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); + "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" + " com.google.protobuf.UnknownFieldSet.newBuilder();\n"); } else { printer->Print( - "case 0:\n" // zero signals EOF / limit reached - " return this;\n" - "default: {\n" - " if (!parseUnknownField(input, extensionRegistry, tag)) {\n" - " return this;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); + "com.google.protobuf.ByteString.Output unknownFieldsOutput =\n" + " com.google.protobuf.ByteString.newOutput();\n" + "com.google.protobuf.CodedOutputStream unknownFieldsCodedOutput =\n" + " com.google.protobuf.CodedOutputStream.newInstance(\n" + " unknownFieldsOutput);\n"); } + printer->Print( + "try {\n"); + printer->Indent(); + + printer->Print( + "boolean done = false;\n" + "while (!done) {\n"); + printer->Indent(); + + printer->Print( + "int tag = input.readTag();\n" + "switch (tag) {\n"); + printer->Indent(); + + printer->Print( + "case 0:\n" // zero signals EOF / limit reached + " done = true;\n" + " break;\n" + "default: {\n" + " if (!parseUnknownField(input,$unknown_fields$\n" + " extensionRegistry, tag)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n", + "unknown_fields", UseUnknownFieldSet(descriptor_) + ? " unknownFields," : " unknownFieldsCodedOutput,"); + for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = sorted_fields[i]; uint32 tag = WireFormatLite::MakeTag(field->number(), @@ -890,92 +1562,104 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { printer->Outdent(); printer->Outdent(); - printer->Outdent(); printer->Print( - " }\n" // switch (tag) - " }\n" // while (true) - "}\n" - "\n"); -} + " }\n" // switch (tag) + "}\n"); // while (!done) -// =================================================================== - -void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { + printer->Outdent(); printer->Print( - "public final boolean isInitialized() {\n"); + "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" + " throw e.setUnfinishedMessage(this);\n" + "} catch (java.io.IOException e) {\n" + " throw new com.google.protobuf.InvalidProtocolBufferException(\n" + " e.getMessage()).setUnfinishedMessage(this);\n" + "} finally {\n"); printer->Indent(); - // Check that all required fields in this message are set. - // TODO(kenton): We can optimize this when we switch to putting all the - // "has" fields into a single bitfield. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - - if (field->is_required()) { - printer->Print( - "if (!has$name$) return false;\n", - "name", UnderscoresToCapitalizedCamelCase(field)); - } - } - - // Now check that all embedded messages are initialized. + // Make repeated field list immutable. for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (GetJavaType(field) == JAVATYPE_MESSAGE && - HasRequiredFields(field->message_type())) { - switch (field->label()) { - case FieldDescriptor::LABEL_REQUIRED: - printer->Print( - "if (!get$name$().isInitialized()) return false;\n", - "type", ClassName(field->message_type()), - "name", UnderscoresToCapitalizedCamelCase(field)); - break; - case FieldDescriptor::LABEL_OPTIONAL: - printer->Print( - "if (has$name$()) {\n" - " if (!get$name$().isInitialized()) return false;\n" - "}\n", - "type", ClassName(field->message_type()), - "name", UnderscoresToCapitalizedCamelCase(field)); - break; - case FieldDescriptor::LABEL_REPEATED: - printer->Print( - "for ($type$ element : get$name$List()) {\n" - " if (!element.isInitialized()) return false;\n" - "}\n", - "type", ClassName(field->message_type()), - "name", UnderscoresToCapitalizedCamelCase(field)); - break; - } - } + const FieldDescriptor* field = sorted_fields[i]; + field_generators_.get(field).GenerateParsingDoneCode(printer); } - if (descriptor_->extension_range_count() > 0) { + // Make unknown fields immutable. + if (UseUnknownFieldSet(descriptor_)) { printer->Print( - "if (!extensionsAreInitialized()) return false;\n"); + "this.unknownFields = unknownFields.build();\n"); + } else { + printer->Print( + "try {\n" + " unknownFieldsCodedOutput.flush();\n" + "} catch (java.io.IOException e) {\n" + "// Should not happen\n" + "} finally {\n" + " unknownFields = unknownFieldsOutput.toByteString();\n" + "}\n"); } + // Make extensions immutable. + printer->Print( + "makeExtensionsImmutable();\n"); + + printer->Outdent(); printer->Outdent(); printer->Print( - " return true;\n" - "}\n" - "\n"); + " }\n" // finally + "}\n"); } // =================================================================== - -void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator(descriptor_->extension(i)) - .GenerateRegistrationCode(printer); +void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { + printer->Print( + "public static com.google.protobuf.Parser<$classname$> PARSER =\n" + " new com.google.protobuf.AbstractParser<$classname$>() {\n", + "classname", descriptor_->name()); + printer->Indent(); + printer->Print( + "public $classname$ parsePartialFrom(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n", + "classname", descriptor_->name()); + if (HasGeneratedMethods(descriptor_)) { + printer->Print( + " return new $classname$(input, extensionRegistry);\n", + "classname", descriptor_->name()); + } else { + // When parsing constructor isn't generated, use builder to parse messages. + // Note, will fallback to use reflection based mergeFieldFrom() in + // AbstractMessage.Builder. + printer->Indent(); + printer->Print( + "Builder builder = newBuilder();\n" + "try {\n" + " builder.mergeFrom(input, extensionRegistry);\n" + "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" + " throw e.setUnfinishedMessage(builder.buildPartial());\n" + "} catch (java.io.IOException e) {\n" + " throw new com.google.protobuf.InvalidProtocolBufferException(\n" + " e.getMessage()).setUnfinishedMessage(builder.buildPartial());\n" + "}\n" + "return builder.buildPartial();\n"); + printer->Outdent(); } + printer->Print( + "}\n"); + printer->Outdent(); + printer->Print( + "};\n" + "\n"); - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator(descriptor_->nested_type(i)) - .GenerateExtensionRegistrationCode(printer); - } + printer->Print( + "@java.lang.Override\n" + "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" + " return PARSER;\n" + "}\n" + "\n", + "classname", descriptor_->name()); } + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index 50ffae0..406910d 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -36,11 +36,17 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ #include -#include +#include #include namespace google { namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } namespace io { class Printer; // printer.h } @@ -53,25 +59,55 @@ namespace java { class MessageGenerator { public: explicit MessageGenerator(const Descriptor* descriptor); - ~MessageGenerator(); + virtual ~MessageGenerator(); // All static variables have to be declared at the top-level of the file // so that we can control initialization order, which is important for // DescriptorProto bootstrapping to work. - void GenerateStaticVariables(io::Printer* printer); + virtual void GenerateStaticVariables(io::Printer* printer) = 0; // Output code which initializes the static variables generated by // GenerateStaticVariables(). - void GenerateStaticVariableInitializers(io::Printer* printer); + virtual void GenerateStaticVariableInitializers(io::Printer* printer) = 0; // Generate the class itself. - void Generate(io::Printer* printer); + virtual void Generate(io::Printer* printer) = 0; + + // Generates the base interface that both the class and its builder implement + virtual void GenerateInterface(io::Printer* printer) = 0; // Generate code to register all contained extensions with an // ExtensionRegistry. - void GenerateExtensionRegistrationCode(io::Printer* printer); + virtual void GenerateExtensionRegistrationCode(io::Printer* printer) = 0; + + protected: + const Descriptor* descriptor_; private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); +}; + +class ImmutableMessageGenerator : public MessageGenerator { + public: + explicit ImmutableMessageGenerator(const Descriptor* descriptor, + Context* context); + virtual ~ImmutableMessageGenerator(); + + virtual void Generate(io::Printer* printer); + virtual void GenerateInterface(io::Printer* printer); + virtual void GenerateExtensionRegistrationCode(io::Printer* printer); + virtual void GenerateStaticVariables(io::Printer* printer); + virtual void GenerateStaticVariableInitializers(io::Printer* printer); + + private: + enum UseMemoization { + MEMOIZE, + DONT_MEMOIZE + }; + + void GenerateFieldAccessorTable(io::Printer* printer); + void GenerateFieldAccessorTableInitializer(io::Printer* printer); + void GenerateMessageSerializationMethods(io::Printer* printer); void GenerateParseFromMethods(io::Printer* printer); void GenerateSerializeOneField(io::Printer* printer, @@ -81,13 +117,19 @@ class MessageGenerator { void GenerateBuilder(io::Printer* printer); void GenerateCommonBuilderMethods(io::Printer* printer); + void GenerateDescriptorMethods(io::Printer* printer); void GenerateBuilderParsingMethods(io::Printer* printer); - void GenerateIsInitialized(io::Printer* printer); + void GenerateIsInitialized(io::Printer* printer, + UseMemoization useMemoization); + void GenerateEqualsAndHashCode(io::Printer* printer); + void GenerateParser(io::Printer* printer); + void GenerateParsingConstructor(io::Printer* printer); - const Descriptor* descriptor_; - FieldGeneratorMap field_generators_; + Context* context_; + ClassNameResolver* name_resolver_; + FieldGeneratorMap field_generators_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index 71edc02..80b9a38 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -35,8 +35,11 @@ #include #include +#include #include +#include #include +#include #include #include #include @@ -48,88 +51,413 @@ namespace java { namespace { -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. void SetMessageVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, map* variables) { - (*variables)["name"] = - UnderscoresToCamelCase(descriptor); - (*variables)["capitalized_name"] = - UnderscoresToCapitalizedCamelCase(descriptor); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["type"] = ClassName(descriptor->message_type()); + SetCommonFieldVariables(descriptor, info, variables); + + (*variables)["type"] = + name_resolver->GetImmutableClassName(descriptor->message_type()); + (*variables)["mutable_type"] = + name_resolver->GetMutableClassName(descriptor->message_type()); (*variables)["group_or_message"] = (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + if (SupportFieldPresence(descriptor->file())) { + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_message"] = + GenerateSetBit(messageBitIndex) + ";"; + (*variables)["set_has_field_bit_builder"] = + GenerateSetBit(builderBitIndex) + ";"; + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex) + ";"; + + (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + } else { + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["set_has_field_bit_builder"] = ""; + (*variables)["clear_has_field_bit_builder"] = ""; + + (*variables)["is_field_present_message"] = + (*variables)["name"] + "_ != null"; + } + + // For repated builders, one bit is used for whether the array is immutable. + (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); + + // For repeated fields, one bit is used for whether the array is immutable + // in the parsing constructor. + (*variables)["get_mutable_bit_parser"] = + GenerateGetBitMutableLocal(builderBitIndex); + (*variables)["set_mutable_bit_parser"] = + GenerateSetBitMutableLocal(builderBitIndex); + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); } } // namespace // =================================================================== -MessageFieldGenerator:: -MessageFieldGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { - SetMessageVariables(descriptor, &variables_); +ImmutableMessageFieldGenerator:: +ImmutableMessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } -MessageFieldGenerator::~MessageFieldGenerator() {} +ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {} -void MessageFieldGenerator:: +int ImmutableMessageFieldGenerator::GetNumBitsForMessage() const { + return 1; +} + +int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void ImmutableMessageFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + // TODO(jonp): In the future, consider having a method specific to the + // interface so that builders can choose dynamically to either return a + // message or a nested builder, so that asking for the interface doesn't + // cause a message to ever be built. + if (SupportFieldPresence(descriptor_->file()) || + descriptor_->containing_oneof() == NULL) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$();\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n"); + } +} + +void ImmutableMessageFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private boolean has$capitalized_name$;\n" - "private $type$ $name$_;\n" - "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n" - "public $type$ get$capitalized_name$() { return $name$_; }\n"); + "private $type$ $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder " + "get$capitalized_name$OrBuilder() {\n" + " return $name$_;\n" + "}\n"); + } + } else { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $name$_ != null;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder " + "get$capitalized_name$OrBuilder() {\n" + " return get$capitalized_name$();\n" + "}\n"); + } + } } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition( + io::Printer* printer, + const char* regular_case, + const char* nested_builder_case) const { + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, "if ($name$Builder_ == null) {\n"); + printer->Indent(); + printer->Print(variables_, regular_case); + printer->Outdent(); + printer->Print("} else {\n"); + printer->Indent(); + printer->Print(variables_, nested_builder_case); + printer->Outdent(); + printer->Print("}\n"); + } else { + printer->Print(variables_, regular_case); + } +} + +void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction( + io::Printer* printer, + const char* method_prototype, + const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const { + printer->Print(variables_, method_prototype); + printer->Print(" {\n"); + printer->Indent(); + PrintNestedBuilderCondition(printer, regular_case, nested_builder_case); + if (trailing_code != NULL) { + printer->Print(variables_, trailing_code); + } + printer->Outdent(); + printer->Print("}\n"); +} + +void ImmutableMessageFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { - printer->Print(variables_, - "public boolean has$capitalized_name$() {\n" - " return result.has$capitalized_name$();\n" - "}\n" - "public $type$ get$capitalized_name$() {\n" - " return result.get$capitalized_name$();\n" - "}\n" - "public Builder set$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " result.has$capitalized_name$ = true;\n" - " result.$name$_ = value;\n" - " return this;\n" - "}\n" - "public Builder set$capitalized_name$($type$.Builder builderForValue) {\n" - " result.has$capitalized_name$ = true;\n" - " result.$name$_ = builderForValue.build();\n" - " return this;\n" - "}\n" - "public Builder merge$capitalized_name$($type$ value) {\n" - " if (result.has$capitalized_name$() &&\n" - " result.$name$_ != $type$.getDefaultInstance()) {\n" - " result.$name$_ =\n" - " $type$.newBuilder(result.$name$_).mergeFrom(value).buildPartial();\n" - " } else {\n" - " result.$name$_ = value;\n" - " }\n" - " result.has$capitalized_name$ = true;\n" - " return this;\n" + // When using nested-builders, the code initially works just like the + // non-nested builder case. It only creates a nested builder lazily on + // demand and then forever delegates to it after creation. + + bool support_field_presence = SupportFieldPresence(descriptor_->file()); + + if (support_field_presence) { + printer->Print(variables_, + // Used when the builder is null. + "private $type$ $name$_ = $type$.getDefaultInstance();\n"); + } else { + printer->Print(variables_, + "private $type$ $name$_ = null;\n"); + } + + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" + "\n"); + } + + // The comments above the methods below are based on a hypothetical + // field of type "Field" called "Field". + + // boolean hasField() + WriteFieldDocComment(printer, descriptor_); + if (support_field_presence) { + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + } else { + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $name$Builder_ != null || $name$_ != null;\n" + "}\n"); + } + + // Field getField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public $type$ get$capitalized_name$()", + + support_field_presence + ? "return $name$_;\n" + : "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n", + + "return $name$Builder_.getMessage();\n", + + NULL); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" "}\n" - "public Builder clear$capitalized_name$() {\n" - " result.has$capitalized_name$ = false;\n" - " result.$name$_ = $type$.getDefaultInstance();\n" - " return this;\n" - "}\n"); + "$name$_ = value;\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(value);\n", + + "$set_has_field_bit_builder$\n" + "return this;\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "$name$_ = builderForValue.build();\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(builderForValue.build());\n", + + "$set_has_field_bit_builder$\n" + "return this;\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder merge$capitalized_name$($type$ value)", + + support_field_presence + ? "if ($get_has_field_bit_builder$ &&\n" + " $name$_ != $type$.getDefaultInstance()) {\n" + " $name$_ =\n" + " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" + "} else {\n" + " $name$_ = value;\n" + "}\n" + "$on_changed$\n" + : "if ($name$_ != null) {\n" + " $name$_ =\n" + " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" + "} else {\n" + " $name$_ = value;\n" + "}\n" + "$on_changed$\n", + + "$name$Builder_.mergeFrom(value);\n", + + "$set_has_field_bit_builder$\n" + "return this;\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + support_field_presence + ? "$name$_ = $type$.getDefaultInstance();\n" + "$on_changed$\n" + : "$name$_ = null;\n" + "$on_changed$\n", + + support_field_presence + ? "$name$Builder_.clear();\n" + : "$name$_ = null;\n" + "$name$Builder_ = null;\n", + + "$clear_has_field_bit_builder$\n" + "return this;\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" + " $set_has_field_bit_builder$\n" + " $on_changed$\n" + " return get$capitalized_name$FieldBuilder().getBuilder();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilder();\n" + " } else {\n"); + if (support_field_presence) { + printer->Print(variables_, + " return $name$_;\n"); + } else { + printer->Print(variables_, + " return $name$_ == null ?\n" + " $type$.getDefaultInstance() : $name$_;\n"); + } + printer->Print(variables_, + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " get$capitalized_name$(),\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); + } } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "get$capitalized_name$FieldBuilder();\n"); + } +} + + +void ImmutableMessageFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n"); + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n"); + } } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + PrintNestedBuilderCondition(printer, + "$name$_ = $type$.getDefaultInstance();\n", + + "$name$Builder_.clear();\n"); + printer->Print(variables_, "$clear_has_field_bit_builder$\n"); + } else { + PrintNestedBuilderCondition(printer, + "$name$_ = null;\n", + + "$name$_ = null;\n" + "$name$Builder_ = null;\n"); + } +} + +void ImmutableMessageFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { printer->Print(variables_, "if (other.has$capitalized_name$()) {\n" @@ -137,196 +465,876 @@ GenerateMergingCode(io::Printer* printer) const { "}\n"); } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - // Nothing to do for singular fields. + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); + } + + PrintNestedBuilderCondition(printer, + "result.$name$_ = $name$_;\n", + + "result.$name$_ = $name$Builder_.build();\n"); } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, - "$type$.Builder subBuilder = $type$.newBuilder();\n" - "if (has$capitalized_name$()) {\n" - " subBuilder.mergeFrom(get$capitalized_name$());\n" + "$type$.Builder subBuilder = null;\n" + "if ($is_field_present_message$) {\n" + " subBuilder = $name$_.toBuilder();\n" "}\n"); if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, - "input.readGroup($number$, subBuilder, extensionRegistry);\n"); + "$name$_ = input.readGroup($number$, $type$.PARSER,\n" + " extensionRegistry);\n"); } else { printer->Print(variables_, - "input.readMessage(subBuilder, extensionRegistry);\n"); + "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n"); } printer->Print(variables_, - "set$capitalized_name$(subBuilder.buildPartial());\n"); + "if (subBuilder != null) {\n" + " subBuilder.mergeFrom($name$_);\n" + " $name$_ = subBuilder.buildPartial();\n" + "}\n" + "$set_has_field_bit_message$\n"); } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // noop for messages. +} + +void ImmutableMessageFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if (has$capitalized_name$()) {\n" - " output.write$group_or_message$($number$, get$capitalized_name$());\n" + "if ($is_field_present_message$) {\n" + " output.write$group_or_message$($number$, $name$_);\n" "}\n"); } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if (has$capitalized_name$()) {\n" + "if ($is_field_present_message$) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, get$capitalized_name$());\n" + " .compute$group_or_message$Size($number$, $name$_);\n" "}\n"); } -string MessageFieldGenerator::GetBoxedType() const { - return ClassName(descriptor_->message_type()); +void ImmutableMessageFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); +} + +void ImmutableMessageFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); +} + +string ImmutableMessageFieldGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->message_type()); } // =================================================================== -RepeatedMessageFieldGenerator:: -RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { - SetMessageVariables(descriptor, &variables_); +ImmutableMessageOneofFieldGenerator:: +ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableMessageFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); } -RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} +ImmutableMessageOneofFieldGenerator:: +~ImmutableMessageOneofFieldGenerator() {} -void RepeatedMessageFieldGenerator:: +void ImmutableMessageOneofFieldGenerator:: GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "private java.util.List<$type$> $name$_ =\n" - " java.util.Collections.emptyList();\n" - "public java.util.List<$type$> get$capitalized_name$List() {\n" - " return $name$_;\n" // note: unmodifiable list - "}\n" - "public int get$capitalized_name$Count() { return $name$_.size(); }\n" - "public $type$ get$capitalized_name$(int index) {\n" - " return $name$_.get(index);\n" + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" "}\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); + } } -void RepeatedMessageFieldGenerator:: +void ImmutableMessageOneofFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { - printer->Print(variables_, - // Note: We return an unmodifiable list because otherwise the caller - // could hold on to the returned list and modify it after the message - // has been built, thus mutating the message which is supposed to be - // immutable. - "public java.util.List<$type$> get$capitalized_name$List() {\n" - " return java.util.Collections.unmodifiableList(result.$name$_);\n" + // When using nested-builders, the code initially works just like the + // non-nested builder case. It only creates a nested builder lazily on + // demand and then forever delegates to it after creation. + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" + "\n"); + } + + // The comments above the methods below are based on a hypothetical + // field of type "Field" called "Field". + + if (SupportFieldPresence(descriptor_->file())) { + // boolean hasField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + + // Field getField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public $type$ get$capitalized_name$()", + + "if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" "}\n" - "public int get$capitalized_name$Count() {\n" - " return result.get$capitalized_name$Count();\n" + "return $type$.getDefaultInstance();\n", + + "if ($has_oneof_case_message$) {\n" + " return $name$Builder_.getMessage();\n" "}\n" - "public $type$ get$capitalized_name$(int index) {\n" - " return result.get$capitalized_name$(index);\n" + "return $type$.getDefaultInstance();\n", + + NULL); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" "}\n" - "public Builder set$capitalized_name$(int index, $type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " result.$name$_.set(index, value);\n" - " return this;\n" + "$oneof_name$_ = value;\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(value);\n", + + "$set_oneof_case_message$;\n" + "return this;\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "$oneof_name$_ = builderForValue.build();\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(builderForValue.build());\n", + + "$set_oneof_case_message$;\n" + "return this;\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder merge$capitalized_name$($type$ value)", + + "if ($has_oneof_case_message$ &&\n" + " $oneof_name$_ != $type$.getDefaultInstance()) {\n" + " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n" + " .mergeFrom(value).buildPartial();\n" + "} else {\n" + " $oneof_name$_ = value;\n" "}\n" - "public Builder set$capitalized_name$(int index, " - "$type$.Builder builderForValue) {\n" - " result.$name$_.set(index, builderForValue.build());\n" - " return this;\n" + "$on_changed$\n", + + "if ($has_oneof_case_message$) {\n" + " $name$Builder_.mergeFrom(value);\n" "}\n" - "public Builder add$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" - " }\n" - " result.$name$_.add(value);\n" - " return this;\n" + "$name$Builder_.setMessage(value);\n", + + "$set_oneof_case_message$;\n" + "return this;\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + "if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + "}\n", + + "if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" "}\n" - "public Builder add$capitalized_name$($type$.Builder builderForValue) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" - " }\n" - " result.$name$_.add(builderForValue.build());\n" - " return this;\n" + "$name$Builder_.clear();\n", + + "return this;\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" + " return get$capitalized_name$FieldBuilder().getBuilder();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n" + " return $name$Builder_.getMessageOrBuilder();\n" + " } else {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = $type$.getDefaultInstance();\n" + " }\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " ($type$) $oneof_name$_,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $oneof_name$_ = null;\n" + " }\n" + " $set_oneof_case_message$;\n" + " return $name$Builder_;\n" + "}\n"); + } +} + +void ImmutableMessageOneofFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n"); + printer->Indent(); + + PrintNestedBuilderCondition(printer, + "result.$oneof_name$_ = $oneof_name$_;\n", + + "result.$oneof_name$_ = $name$Builder_.build();\n"); + + printer->Outdent(); + printer->Print("}\n"); +} + +void ImmutableMessageOneofFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "merge$capitalized_name$(other.get$capitalized_name$());\n"); +} + +void ImmutableMessageOneofFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$type$.Builder subBuilder = null;\n" + "if ($has_oneof_case_message$) {\n" + " subBuilder = (($type$) $oneof_name$_).toBuilder();\n" + "}\n"); + + if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { + printer->Print(variables_, + "$oneof_name$_ = input.readGroup($number$, $type$.PARSER,\n" + " extensionRegistry);\n"); + } else { + printer->Print(variables_, + "$oneof_name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n"); + } + + printer->Print(variables_, + "if (subBuilder != null) {\n" + " subBuilder.mergeFrom(($type$) $oneof_name$_);\n" + " $oneof_name$_ = subBuilder.buildPartial();\n" + "}\n"); + printer->Print(variables_, + "$set_oneof_case_message$;\n"); +} + +void ImmutableMessageOneofFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n" + "}\n"); +} + +void ImmutableMessageOneofFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n" + "}\n"); +} + +// =================================================================== + +RepeatedImmutableMessageFieldGenerator:: +RepeatedImmutableMessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +RepeatedImmutableMessageFieldGenerator:: +~RepeatedImmutableMessageFieldGenerator() {} + +int RepeatedImmutableMessageFieldGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedImmutableMessageFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void RepeatedImmutableMessageFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + // TODO(jonp): In the future, consider having methods specific to the + // interface so that builders can choose dynamically to either return a + // message or a nested builder, so that asking for the interface doesn't + // cause a message to ever be built. + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List<$type$> \n" + " get$capitalized_name$List();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$(int index);\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List \n" + " get$capitalized_name$OrBuilderList();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index);\n"); + } +} + +void RepeatedImmutableMessageFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private java.util.List<$type$> $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List \n" + " get$capitalized_name$OrBuilderList() {\n" + " return $name$_;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + +} + +void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition( + io::Printer* printer, + const char* regular_case, + const char* nested_builder_case) const { + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, "if ($name$Builder_ == null) {\n"); + printer->Indent(); + printer->Print(variables_, regular_case); + printer->Outdent(); + printer->Print("} else {\n"); + printer->Indent(); + printer->Print(variables_, nested_builder_case); + printer->Outdent(); + printer->Print("}\n"); + } else { + printer->Print(variables_, regular_case); + } +} + +void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction( + io::Printer* printer, + const char* method_prototype, + const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const { + printer->Print(variables_, method_prototype); + printer->Print(" {\n"); + printer->Indent(); + PrintNestedBuilderCondition(printer, regular_case, nested_builder_case); + if (trailing_code != NULL) { + printer->Print(variables_, trailing_code); + } + printer->Outdent(); + printer->Print("}\n"); +} + +void RepeatedImmutableMessageFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // When using nested-builders, the code initially works just like the + // non-nested builder case. It only creates a nested builder lazily on + // demand and then forever delegates to it after creation. + + printer->Print(variables_, + // Used when the builder is null. + // One field is the list and the other field keeps track of whether the + // list is immutable. If it's immutable, the invariant is that it must + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a refererence to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + "private java.util.List<$type$> $name$_ =\n" + " java.util.Collections.emptyList();\n" + + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new java.util.ArrayList<$type$>($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" "}\n" - "public Builder addAll$capitalized_name$(\n" - " java.lang.Iterable values) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" - " }\n" - " super.addAll(values, result.$name$_);\n" - " return this;\n" + "\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" + "\n"); + } + + // The comments above the methods below are based on a hypothetical + // repeated field of type "Field" called "RepeatedField". + + // List getRepeatedFieldList() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List()", + + "return java.util.Collections.unmodifiableList($name$_);\n", + "return $name$Builder_.getMessageList();\n", + + NULL); + + // int getRepeatedFieldCount() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public int get$capitalized_name$Count()", + + "return $name$_.size();\n", + "return $name$Builder_.getCount();\n", + + NULL); + + // Field getRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public $type$ get$capitalized_name$(int index)", + + "return $name$_.get(index);\n", + + "return $name$Builder_.getMessage(index);\n", + + NULL); + + // Builder setRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value)", + "if (value == null) {\n" + " throw new NullPointerException();\n" "}\n" - "public Builder clear$capitalized_name$() {\n" - " result.$name$_ = java.util.Collections.emptyList();\n" - " return this;\n" - "}\n"); + "ensure$capitalized_name$IsMutable();\n" + "$name$_.set(index, value);\n" + "$on_changed$\n", + "$name$Builder_.setMessage(index, value);\n", + "return this;\n"); + + // Builder setRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.set(index, builderForValue.build());\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(index, builderForValue.build());\n", + + "return this;\n"); + + // Builder addRepeatedField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(value);\n" + + "$on_changed$\n", + + "$name$Builder_.addMessage(value);\n", + + "return this;\n"); + + // Builder addRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(index, value);\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(index, value);\n", + + "return this;\n"); + + // Builder addRepeatedField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(builderForValue.build());\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(builderForValue.build());\n", + + "return this;\n"); + + // Builder addRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(index, builderForValue.build());\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(index, builderForValue.build());\n", + + "return this;\n"); + + // Builder addAllRepeatedField(Iterable values) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values)", + + "ensure$capitalized_name$IsMutable();\n" + "com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" + " values, $name$_);\n" + "$on_changed$\n", + + "$name$Builder_.addAllMessages(values);\n", + + "return this;\n"); + + // Builder clearAllRepeatedField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n" + "$on_changed$\n", + + "$name$Builder_.clear();\n", + + "return this;\n"); + + // Builder removeRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder remove$capitalized_name$(int index)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.remove(index);\n" + "$on_changed$\n", + + "$name$Builder_.remove(index);\n", + + "return this;\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" + " if ($name$Builder_ == null) {\n" + " return $name$_.get(index);" + " } else {\n" + " return $name$Builder_.getMessageOrBuilder(index);\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List \n" + " get$capitalized_name$OrBuilderList() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilderList();\n" + " } else {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " $type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " index, $type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$.Builder> \n" + " get$capitalized_name$BuilderList() {\n" + " return get$capitalized_name$FieldBuilder().getBuilderList();\n" + "}\n" + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " $name$_,\n" + " $get_mutable_bit_builder$,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); + } +} + +void RepeatedImmutableMessageFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + printer->Print(variables_, + "get$capitalized_name$FieldBuilder();\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - // Initialized inline. + printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); +} + +void RepeatedImmutableMessageFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + PrintNestedBuilderCondition(printer, + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n", + + "$name$Builder_.clear();\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, + // The code below does two optimizations (non-nested builder case): + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. + PrintNestedBuilderCondition(printer, + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n", + "if (!other.$name$_.isEmpty()) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" + " if ($name$Builder_.isEmpty()) {\n" + " $name$Builder_.dispose();\n" + " $name$Builder_ = null;\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " $name$Builder_ = \n" + " com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n" + " get$capitalized_name$FieldBuilder() : null;\n" + " } else {\n" + " $name$Builder_.addAllMessages(other.$name$_);\n" " }\n" - " result.$name$_.addAll(other.$name$_);\n" "}\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n" - " result.$name$_ =\n" - " java.util.Collections.unmodifiableList(result.$name$_);\n" - "}\n"); + // The code below (non-nested builder case) ensures that the result has an + // immutable list. If our list is immutable, we can just reuse it. If not, + // we make it immutable. + PrintNestedBuilderCondition(printer, + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n", + + "result.$name$_ = $name$Builder_.build();\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, - "$type$.Builder subBuilder = $type$.newBuilder();\n"); + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ = new java.util.ArrayList<$type$>();\n" + " $set_mutable_bit_parser$;\n" + "}\n"); if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, - "input.readGroup($number$, subBuilder, extensionRegistry);\n"); + "$name$_.add(input.readGroup($number$, $type$.PARSER,\n" + " extensionRegistry));\n"); } else { printer->Print(variables_, - "input.readMessage(subBuilder, extensionRegistry);\n"); + "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n"); } +} +void RepeatedImmutableMessageFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { printer->Print(variables_, - "add$capitalized_name$(subBuilder.buildPartial());\n"); + "if ($get_mutable_bit_parser$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "for ($type$ element : get$capitalized_name$List()) {\n" - " output.write$group_or_message$($number$, element);\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$group_or_message$($number$, $name$_.get(i));\n" "}\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "for ($type$ element : get$capitalized_name$List()) {\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, element);\n" + " .compute$group_or_message$Size($number$, $name$_.get(i));\n" + "}\n"); +} + +void RepeatedImmutableMessageFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedImmutableMessageFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" "}\n"); } -string RepeatedMessageFieldGenerator::GetBoxedType() const { - return ClassName(descriptor_->message_type()); +string RepeatedImmutableMessageFieldGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->message_type()); } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h index 66bdd88..f7b491e 100644 --- a/src/google/protobuf/compiler/java/java_message_field.h +++ b/src/google/protobuf/compiler/java/java_message_field.h @@ -41,55 +41,128 @@ namespace google { namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } +} + +namespace protobuf { namespace compiler { namespace java { -class MessageFieldGenerator : public FieldGenerator { +class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { public: - explicit MessageFieldGenerator(const FieldDescriptor* descriptor); - ~MessageFieldGenerator(); - - // implements FieldGenerator --------------------------------------- + explicit ImmutableMessageFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableMessageFieldGenerator(); + + // implements ImmutableFieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; + + void PrintNestedBuilderCondition(io::Printer* printer, + const char* regular_case, const char* nested_builder_case) const; + void PrintNestedBuilderFunction(io::Printer* printer, + const char* method_prototype, const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldGenerator); }; -class RepeatedMessageFieldGenerator : public FieldGenerator { +class ImmutableMessageOneofFieldGenerator + : public ImmutableMessageFieldGenerator { public: - explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor); - ~RepeatedMessageFieldGenerator(); + ImmutableMessageOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableMessageOneofFieldGenerator(); - // implements FieldGenerator --------------------------------------- + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldGenerator); +}; + +class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator { + public: + explicit RepeatedImmutableMessageFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~RepeatedImmutableMessageFieldGenerator(); + + // implements ImmutableFieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; + + void PrintNestedBuilderCondition(io::Printer* printer, + const char* regular_case, const char* nested_builder_case) const; + void PrintNestedBuilderFunction(io::Printer* printer, + const char* method_prototype, const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_name_resolver.cc b/src/google/protobuf/compiler/java/java_name_resolver.cc new file mode 100644 index 0000000..bc7b814 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_name_resolver.cc @@ -0,0 +1,266 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +#include + +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { +// A suffix that will be appended to the file's outer class name if the name +// conflicts with some other types defined in the file. +const char* kOuterClassNameSuffix = "OuterClass"; + +// Strip package name from a descriptor's full name. +// For example: +// Full name : foo.Bar.Baz +// Package name: foo +// After strip : Bar.Baz +string StripPackageName(const string& full_name, + const FileDescriptor* file) { + if (file->package().empty()) { + return full_name; + } else { + // Strip package name + return full_name.substr(file->package().size() + 1); + } +} + +// Get the name of a message's Java class without package name prefix. +string ClassNameWithoutPackage(const Descriptor* descriptor, + bool immutable) { + return StripPackageName(descriptor->full_name(), + descriptor->file()); +} + +// Get the name of an enum's Java class without package name prefix. +string ClassNameWithoutPackage(const EnumDescriptor* descriptor, + bool immutable) { + // Doesn't append "Mutable" for enum type's name. + const Descriptor* message_descriptor = descriptor->containing_type(); + if (message_descriptor == NULL) { + return descriptor->name(); + } else { + return ClassNameWithoutPackage(message_descriptor, immutable) + + "." + descriptor->name(); + } +} + +// Get the name of a service's Java class without package name prefix. +string ClassNameWithoutPackage(const ServiceDescriptor* descriptor, + bool immutable) { + string full_name = StripPackageName(descriptor->full_name(), + descriptor->file()); + // We don't allow nested service definitions. + GOOGLE_CHECK(full_name.find('.') == string::npos); + return full_name; +} + +// Check whether a given message or its nested types has the given class name. +bool MessageHasConflictingClassName(const Descriptor* message, + const string& classname) { + if (message->name() == classname) return true; + for (int i = 0; i < message->nested_type_count(); ++i) { + if (MessageHasConflictingClassName(message->nested_type(i), classname)) { + return true; + } + } + for (int i = 0; i < message->enum_type_count(); ++i) { + if (message->enum_type(i)->name() == classname) { + return true; + } + } + return false; +} + +} // namespace + +ClassNameResolver::ClassNameResolver() { +} + +ClassNameResolver::~ClassNameResolver() { +} + +string ClassNameResolver::GetFileDefaultImmutableClassName( + const FileDescriptor* file) { + string basename; + string::size_type last_slash = file->name().find_last_of('/'); + if (last_slash == string::npos) { + basename = file->name(); + } else { + basename = file->name().substr(last_slash + 1); + } + return UnderscoresToCamelCase(StripProto(basename), true); +} + +string ClassNameResolver::GetFileImmutableClassName( + const FileDescriptor* file) { + string& class_name = file_immutable_outer_class_names_[file]; + if (class_name.empty()) { + if (file->options().has_java_outer_classname()) { + class_name = file->options().java_outer_classname(); + } else { + class_name = GetFileDefaultImmutableClassName(file); + if (HasConflictingClassName(file, class_name)) { + class_name += kOuterClassNameSuffix; + } + } + } + return class_name; +} + +string ClassNameResolver::GetFileClassName(const FileDescriptor* file, + bool immutable) { + if (immutable) { + return GetFileImmutableClassName(file); + } else { + return "Mutable" + GetFileImmutableClassName(file); + } +} + +// Check whether there is any type defined in the proto file that has +// the given class name. +bool ClassNameResolver::HasConflictingClassName( + const FileDescriptor* file, const string& classname) { + for (int i = 0; i < file->enum_type_count(); i++) { + if (file->enum_type(i)->name() == classname) { + return true; + } + } + for (int i = 0; i < file->service_count(); i++) { + if (file->service(i)->name() == classname) { + return true; + } + } + for (int i = 0; i < file->message_type_count(); i++) { + if (MessageHasConflictingClassName(file->message_type(i), classname)) { + return true; + } + } + return false; +} + +string ClassNameResolver::GetDescriptorClassName( + const FileDescriptor* descriptor) { + return GetFileImmutableClassName(descriptor); +} + +string ClassNameResolver::GetClassName(const FileDescriptor* descriptor, + bool immutable) { + string result = FileJavaPackage(descriptor, immutable); + if (!result.empty()) result += '.'; + result += GetFileClassName(descriptor, immutable); + return result; +} + +// Get the full name of a Java class by prepending the Java package name +// or outer class name. +string ClassNameResolver::GetClassFullName(const string& name_without_package, + const FileDescriptor* file, + bool immutable, + bool multiple_files) { + string result; + if (multiple_files) { + result = FileJavaPackage(file, immutable); + } else { + result = GetClassName(file, immutable); + } + if (!result.empty()) { + result += '.'; + } + result += name_without_package; + return result; +} + +string ClassNameResolver::GetClassName(const Descriptor* descriptor, + bool immutable) { + return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), + descriptor->file(), immutable, + MultipleJavaFiles(descriptor->file(), immutable)); +} + +string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor, + bool immutable) { + return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), + descriptor->file(), immutable, + MultipleJavaFiles(descriptor->file(), immutable)); +} + +string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor, + bool immutable) { + return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), + descriptor->file(), immutable, + MultipleJavaFiles(descriptor->file(), immutable)); +} + +// Get the Java Class style full name of a message. +string ClassNameResolver::GetJavaClassFullName( + const string& name_without_package, + const FileDescriptor* file, + bool immutable) { + string result; + if (MultipleJavaFiles(file, immutable)) { + result = FileJavaPackage(file, immutable); + if (!result.empty()) result += '.'; + } else { + result = GetClassName(file, immutable); + if (!result.empty()) result += '$'; + } + result += StringReplace(name_without_package, ".", "$", true); + return result; +} + +string ClassNameResolver::GetExtensionIdentifierName( + const FieldDescriptor* descriptor, bool immutable) { + return GetClassName(descriptor->containing_type(), immutable) + "." + + descriptor->name(); +} + + +string ClassNameResolver::GetJavaImmutableClassName( + const Descriptor* descriptor) { + return GetJavaClassFullName( + ClassNameWithoutPackage(descriptor, true), + descriptor->file(), true); +} + + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_name_resolver.h b/src/google/protobuf/compiler/java/java_name_resolver.h new file mode 100644 index 0000000..1d3e185 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_name_resolver.h @@ -0,0 +1,124 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ + +#include +#include + +#include + +namespace google { +namespace protobuf { +class Descriptor; +class EnumDescriptor; +class FieldDescriptor; +class FileDescriptor; +class ServiceDescriptor; + +namespace compiler { +namespace java { + +// Used to get the Java class related names for a given descriptor. It caches +// the results to avoid redundant calculation across multiple name queries. +// Thread-safety note: This class is *not* thread-safe. +class ClassNameResolver { + public: + ClassNameResolver(); + ~ClassNameResolver(); + + // Gets the unqualified outer class name for the file. + string GetFileClassName(const FileDescriptor* file, bool immutable); + // Gets the unqualified immutable outer class name of a file. + string GetFileImmutableClassName(const FileDescriptor* file); + // Gets the unqualified default immutable outer class name of a file + // (converted from the proto file's name). + string GetFileDefaultImmutableClassName(const FileDescriptor* file); + + // Check whether there is any type defined in the proto file that has + // the given class name. + bool HasConflictingClassName(const FileDescriptor* file, + const string& classname); + + // Gets the name of the outer class that holds descriptor information. + // Descriptors are shared between immutable messages and mutable messages. + // Since both of them are generated optionally, the descriptors need to be + // put in another common place. + string GetDescriptorClassName(const FileDescriptor* file); + + // Gets the fully-qualified class name corresponding to the given descriptor. + string GetClassName(const Descriptor* descriptor, bool immutable); + string GetClassName(const EnumDescriptor* descriptor, bool immutable); + string GetClassName(const ServiceDescriptor* descriptor, bool immutable); + string GetClassName(const FileDescriptor* descriptor, bool immutable); + + template + string GetImmutableClassName(const DescriptorType* descriptor) { + return GetClassName(descriptor, true); + } + template + string GetMutableClassName(const DescriptorType* descriptor) { + return GetClassName(descriptor, false); + } + + // Gets the fully qualified name of an extension identifier. + string GetExtensionIdentifierName(const FieldDescriptor* descriptor, + bool immutable); + + // Gets the fully qualified name for generated classes in Java convention. + // Nested classes will be separated using '$' instead of '.' + // For example: + // com.package.OuterClass$OuterMessage$InnerMessage + string GetJavaImmutableClassName(const Descriptor* descriptor); + private: + // Get the full name of a Java class by prepending the Java package name + // or outer class name. + string GetClassFullName(const string& name_without_package, + const FileDescriptor* file, + bool immutable, + bool multiple_files); + // Get the Java Class style full name of a message. + string GetJavaClassFullName( + const string& name_without_package, + const FileDescriptor* file, + bool immutable); + // Caches the result to provide better performance. + map file_immutable_outer_class_names_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ClassNameResolver); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc index cfe0188..5257762 100644 --- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc +++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc @@ -34,6 +34,8 @@ // It seemed like parameterizing it would add more complexity than it is // worth. +#include + #include #include #include @@ -56,21 +58,22 @@ class TestGenerator : public CodeGenerator { virtual bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { - TryInsert("Test.java", "outer_class_scope", output_directory); - TryInsert("Test.java", "class_scope:foo.Bar", output_directory); - TryInsert("Test.java", "class_scope:foo.Bar.Baz", output_directory); - TryInsert("Test.java", "builder_scope:foo.Bar", output_directory); - TryInsert("Test.java", "builder_scope:foo.Bar.Baz", output_directory); - TryInsert("Test.java", "enum_scope:foo.Qux", output_directory); + string filename = "Test.java"; + TryInsert(filename, "outer_class_scope", context); + TryInsert(filename, "class_scope:foo.Bar", context); + TryInsert(filename, "class_scope:foo.Bar.Baz", context); + TryInsert(filename, "builder_scope:foo.Bar", context); + TryInsert(filename, "builder_scope:foo.Bar.Baz", context); + TryInsert(filename, "enum_scope:foo.Qux", context); return true; } void TryInsert(const string& filename, const string& insertion_point, - OutputDirectory* output_directory) const { + GeneratorContext* context) const { scoped_ptr output( - output_directory->OpenForInsert(filename, insertion_point)); + context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } @@ -80,16 +83,16 @@ class TestGenerator : public CodeGenerator { // not verify that they are correctly-placed; that would require actually // compiling the output which is a bit more than I care to do for this test. TEST(JavaPluginTest, PluginTest) { - File::WriteStringToFileOrDie( - "syntax = \"proto2\";\n" - "package foo;\n" - "option java_package = \"\";\n" - "option java_outer_classname = \"Test\";\n" - "message Bar {\n" - " message Baz {}\n" - "}\n" - "enum Qux { BLAH = 1; }\n", - TestTempDir() + "/test.proto"); + GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto", + "syntax = \"proto2\";\n" + "package foo;\n" + "option java_package = \"\";\n" + "option java_outer_classname = \"Test\";\n" + "message Bar {\n" + " message Baz {}\n" + "}\n" + "enum Qux { BLAH = 1; }\n", + true)); google::protobuf::compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index f6179bf..031a129 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -35,9 +35,12 @@ #include #include -#include #include +#include +#include #include +#include +#include #include #include #include @@ -72,98 +75,25 @@ const char* PrimitiveTypeName(JavaType type) { return NULL; } -bool IsReferenceType(JavaType type) { - switch (type) { - case JAVATYPE_INT : return false; - case JAVATYPE_LONG : return false; - case JAVATYPE_FLOAT : return false; - case JAVATYPE_DOUBLE : return false; - case JAVATYPE_BOOLEAN: return false; - case JAVATYPE_STRING : return true; - case JAVATYPE_BYTES : return true; - case JAVATYPE_ENUM : return true; - case JAVATYPE_MESSAGE: return true; - - // No default because we want the compiler to complain if any new - // JavaTypes are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return false; -} - -const char* GetCapitalizedType(const FieldDescriptor* field) { - switch (GetType(field)) { - case FieldDescriptor::TYPE_INT32 : return "Int32" ; - case FieldDescriptor::TYPE_UINT32 : return "UInt32" ; - case FieldDescriptor::TYPE_SINT32 : return "SInt32" ; - case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ; - case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; - case FieldDescriptor::TYPE_INT64 : return "Int64" ; - case FieldDescriptor::TYPE_UINT64 : return "UInt64" ; - case FieldDescriptor::TYPE_SINT64 : return "SInt64" ; - case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ; - case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; - case FieldDescriptor::TYPE_FLOAT : return "Float" ; - case FieldDescriptor::TYPE_DOUBLE : return "Double" ; - case FieldDescriptor::TYPE_BOOL : return "Bool" ; - case FieldDescriptor::TYPE_STRING : return "String" ; - case FieldDescriptor::TYPE_BYTES : return "Bytes" ; - case FieldDescriptor::TYPE_ENUM : return "Enum" ; - case FieldDescriptor::TYPE_GROUP : return "Group" ; - case FieldDescriptor::TYPE_MESSAGE : return "Message" ; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; -} - -// For encodings with fixed sizes, returns that size in bytes. Otherwise -// returns -1. -int FixedSize(FieldDescriptor::Type type) { - switch (type) { - case FieldDescriptor::TYPE_INT32 : return -1; - case FieldDescriptor::TYPE_INT64 : return -1; - case FieldDescriptor::TYPE_UINT32 : return -1; - case FieldDescriptor::TYPE_UINT64 : return -1; - case FieldDescriptor::TYPE_SINT32 : return -1; - case FieldDescriptor::TYPE_SINT64 : return -1; - case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; - case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; - case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; - case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; - case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; - case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; - - case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; - case FieldDescriptor::TYPE_ENUM : return -1; - - case FieldDescriptor::TYPE_STRING : return -1; - case FieldDescriptor::TYPE_BYTES : return -1; - case FieldDescriptor::TYPE_GROUP : return -1; - case FieldDescriptor::TYPE_MESSAGE : return -1; - - // No default because we want the compiler to complain if any new - // types are added. - } - GOOGLE_LOG(FATAL) << "Can't get here."; - return -1; -} - void SetPrimitiveVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, map* variables) { - (*variables)["name"] = - UnderscoresToCamelCase(descriptor); - (*variables)["capitalized_name"] = - UnderscoresToCapitalizedCamelCase(descriptor); - (*variables)["number"] = SimpleItoa(descriptor->number()); + SetCommonFieldVariables(descriptor, info, variables); + (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); - (*variables)["default"] = DefaultValue(descriptor); - (*variables)["capitalized_type"] = GetCapitalizedType(descriptor); + (*variables)["field_type"] = (*variables)["type"]; + (*variables)["field_list_type"] = "java.util.List<" + + (*variables)["boxed_type"] + ">"; + (*variables)["empty_list"] = "java.util.Collections.emptyList()"; + (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ? + "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver)); + (*variables)["capitalized_type"] = + GetCapitalizedType(descriptor, /* immutable = */ true); (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); (*variables)["tag_size"] = SimpleItoa( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); @@ -175,129 +105,517 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, } else { (*variables)["null_check"] = ""; } + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; int fixed_size = FixedSize(GetType(descriptor)); if (fixed_size != -1) { (*variables)["fixed_size"] = SimpleItoa(fixed_size); } + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + if (SupportFieldPresence(descriptor->file())) { + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_message"] = + GenerateSetBit(messageBitIndex) + ";"; + (*variables)["set_has_field_bit_builder"] = + GenerateSetBit(builderBitIndex) + ";"; + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex) + ";"; + + (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + } else { + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["set_has_field_bit_builder"] = ""; + (*variables)["clear_has_field_bit_builder"] = ""; + + if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { + (*variables)["is_field_present_message"] = + "!" + (*variables)["name"] + "_.isEmpty()"; + } else { + (*variables)["is_field_present_message"] = + (*variables)["name"] + "_ != " + (*variables)["default"]; + } + } + + // For repated builders, one bit is used for whether the array is immutable. + (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); + + // For repeated fields, one bit is used for whether the array is immutable + // in the parsing constructor. + (*variables)["get_mutable_bit_parser"] = + GenerateGetBitMutableLocal(builderBitIndex); + (*variables)["set_mutable_bit_parser"] = + GenerateSetBitMutableLocal(builderBitIndex); + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); } + } // namespace // =================================================================== -PrimitiveFieldGenerator:: -PrimitiveFieldGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { - SetPrimitiveVariables(descriptor, &variables_); +ImmutablePrimitiveFieldGenerator:: +ImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } -PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} +ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {} + +int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { + return 1; +} + +int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$();\n"); +} + +void ImmutablePrimitiveFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private boolean has$capitalized_name$;\n" - "private $type$ $name$_ = $default$;\n" - "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n" - "public $type$ get$capitalized_name$() { return $name$_; }\n"); + "private $field_type$ $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, - "public boolean has$capitalized_name$() {\n" - " return result.has$capitalized_name$();\n" - "}\n" - "public $type$ get$capitalized_name$() {\n" - " return result.get$capitalized_name$();\n" - "}\n" - "public Builder set$capitalized_name$($type$ value) {\n" + "private $field_type$ $name$_ $default_init$;\n"); + + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" "$null_check$" - " result.has$capitalized_name$ = true;\n" - " result.$name$_ = value;\n" + " $set_has_field_bit_builder$\n" + " $name$_ = value;\n" + " $on_changed$\n" " return this;\n" - "}\n" - "public Builder clear$capitalized_name$() {\n" - " result.has$capitalized_name$ = false;\n"); + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $clear_has_field_bit_builder$\n"); JavaType type = GetJavaType(descriptor_); if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) { // The default value is not a simple literal so we want to avoid executing // it multiple times. Instead, get the default out of the default instance. printer->Print(variables_, - " result.$name$_ = getDefaultInstance().get$capitalized_name$();\n"); + " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); } else { printer->Print(variables_, - " result.$name$_ = $default$;\n"); + " $name$_ = $default$;\n"); } printer->Print(variables_, + " $on_changed$\n" " return this;\n" "}\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + +void ImmutablePrimitiveFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - // Initialized inline. + printer->Print(variables_, "$name$_ = $default$;\n"); } -void PrimitiveFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { +void ImmutablePrimitiveFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "$name$_ = $default$;\n" + "$clear_has_field_bit_builder$\n"); +} + +void ImmutablePrimitiveFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); + } else { + printer->Print(variables_, + "if (other.get$capitalized_name$() != $default$) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); + } } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - // Nothing to do here for primitive types. + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); + } + printer->Print(variables_, + "result.$name$_ = $name$_;\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, - "set$capitalized_name$(input.read$capitalized_type$());\n"); + "$set_has_field_bit_message$\n" + "$name$_ = input.read$capitalized_type$();\n"); +} + +void ImmutablePrimitiveFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // noop for primitives. } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if (has$capitalized_name$()) {\n" - " output.write$capitalized_type$($number$, get$capitalized_name$());\n" + "if ($is_field_present_message$) {\n" + " output.write$capitalized_type$($number$, $name$_);\n" "}\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if (has$capitalized_name$()) {\n" + "if ($is_field_present_message$) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$Size($number$, get$capitalized_name$());\n" + " .compute$capitalized_type$Size($number$, $name$_);\n" "}\n"); } -string PrimitiveFieldGenerator::GetBoxedType() const { +void ImmutablePrimitiveFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + switch (GetJavaType(descriptor_)) { + case JAVATYPE_INT: + case JAVATYPE_LONG: + case JAVATYPE_BOOLEAN: + printer->Print(variables_, + "result = result && (get$capitalized_name$()\n" + " == other.get$capitalized_name$());\n"); + break; + + case JAVATYPE_FLOAT: + printer->Print(variables_, + "result = result && (\n" + " java.lang.Float.floatToIntBits(get$capitalized_name$())\n" + " == java.lang.Float.floatToIntBits(\n" + " other.get$capitalized_name$()));\n"); + break; + + case JAVATYPE_DOUBLE: + printer->Print(variables_, + "result = result && (\n" + " java.lang.Double.doubleToLongBits(get$capitalized_name$())\n" + " == java.lang.Double.doubleToLongBits(\n" + " other.get$capitalized_name$()));\n"); + break; + + case JAVATYPE_STRING: + case JAVATYPE_BYTES: + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); + break; + + case JAVATYPE_ENUM: + case JAVATYPE_MESSAGE: + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } +} + +void ImmutablePrimitiveFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n"); + switch (GetJavaType(descriptor_)) { + case JAVATYPE_INT: + printer->Print(variables_, + "hash = (53 * hash) + get$capitalized_name$();\n"); + break; + + case JAVATYPE_LONG: + printer->Print(variables_, + "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" + " get$capitalized_name$());\n"); + break; + + case JAVATYPE_BOOLEAN: + printer->Print(variables_, + "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n" + " get$capitalized_name$());\n"); + break; + + case JAVATYPE_FLOAT: + printer->Print(variables_, + "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n" + " get$capitalized_name$());\n"); + break; + + case JAVATYPE_DOUBLE: + printer->Print(variables_, + "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" + " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n"); + break; + + case JAVATYPE_STRING: + case JAVATYPE_BYTES: + printer->Print(variables_, + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); + break; + + case JAVATYPE_ENUM: + case JAVATYPE_MESSAGE: + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } +} + +string ImmutablePrimitiveFieldGenerator::GetBoxedType() const { return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); } // =================================================================== -RepeatedPrimitiveFieldGenerator:: -RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { - SetPrimitiveVariables(descriptor, &variables_); +ImmutablePrimitiveOneofFieldGenerator:: +ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutablePrimitiveFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); } -RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} +ImmutablePrimitiveOneofFieldGenerator:: +~ImmutablePrimitiveOneofFieldGenerator() {} -void RepeatedPrimitiveFieldGenerator:: +void ImmutablePrimitiveOneofFieldGenerator:: GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($boxed_type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n"); +} + + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($boxed_type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "private java.util.List<$boxed_type$> $name$_ =\n" - " java.util.Collections.emptyList();\n" - "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n" + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + "$null_check$" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + " }\n" + " return this;\n" + "}\n"); +} + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " result.$oneof_name$_ = $oneof_name$_;\n" + "}\n"); +} + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "set$capitalized_name$(other.get$capitalized_name$());\n"); +} + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$set_oneof_case_message$;\n" + "$oneof_name$_ = input.read$capitalized_type$();\n"); +} + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.write$capitalized_type$(\n" + " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n" + "}\n"); +} + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$capitalized_type$Size(\n" + " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n" + "}\n"); +} + +// =================================================================== + +RepeatedImmutablePrimitiveFieldGenerator:: +RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +RepeatedImmutablePrimitiveFieldGenerator:: +~RepeatedImmutablePrimitiveFieldGenerator() {} + +int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void RepeatedImmutablePrimitiveFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$(int index);\n"); +} + + +void RepeatedImmutablePrimitiveFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private $field_list_type$ $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$boxed_type$>\n" + " get$capitalized_name$List() {\n" " return $name$_;\n" // note: unmodifiable list - "}\n" - "public int get$capitalized_name$Count() { return $name$_.size(); }\n" - "public $type$ get$capitalized_name$(int index) {\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" " return $name$_.get(index);\n" "}\n"); @@ -308,92 +626,170 @@ GenerateMembers(io::Printer* printer) const { } } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { + // One field is the list and the bit field keeps track of whether the + // list is immutable. If it's immutable, the invariant is that it must + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a refererence to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + printer->Print(variables_, + "private $field_list_type$ $name$_ = $empty_list$;\n"); + printer->Print(variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new java.util.ArrayList<$boxed_type$>($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n"); + // Note: We return an unmodifiable list because otherwise the caller // could hold on to the returned list and modify it after the message // has been built, thus mutating the message which is supposed to be // immutable. - "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n" - " return java.util.Collections.unmodifiableList(result.$name$_);\n" - "}\n" - "public int get$capitalized_name$Count() {\n" - " return result.get$capitalized_name$Count();\n" - "}\n" - "public $type$ get$capitalized_name$(int index) {\n" - " return result.get$capitalized_name$(index);\n" - "}\n" - "public Builder set$capitalized_name$(int index, $type$ value) {\n" + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$boxed_type$>\n" + " get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value) {\n" "$null_check$" - " result.$name$_.set(index, value);\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + " $on_changed$\n" " return this;\n" - "}\n" - "public Builder add$capitalized_name$($type$ value) {\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" "$null_check$" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n" - " }\n" - " result.$name$_.add(value);\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" " return this;\n" - "}\n" - "public Builder addAll$capitalized_name$(\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder addAll$capitalized_name$(\n" " java.lang.Iterable values) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n" - " }\n" - " super.addAll(values, result.$name$_);\n" + " ensure$capitalized_name$IsMutable();\n" + " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" + " values, $name$_);\n" + " $on_changed$\n" " return this;\n" - "}\n" - "public Builder clear$capitalized_name$() {\n" - " result.$name$_ = java.util.Collections.emptyList();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $name$_ = $empty_list$;\n" + " $clear_mutable_bit_builder$;\n" + " $on_changed$\n" " return this;\n" "}\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - // Initialized inline. + printer->Print(variables_, "$name$_ = $empty_list$;\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $empty_list$;\n" + "$clear_mutable_bit_builder$;\n"); +} + +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations: + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. printer->Print(variables_, "if (!other.$name$_.isEmpty()) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" " }\n" - " result.$name$_.addAll(other.$name$_);\n" + " $on_changed$\n" "}\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { + // The code below ensures that the result has an immutable list. If our + // list is immutable, we can just reuse it. If not, we make it immutable. printer->Print(variables_, - "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n" - " result.$name$_ =\n" - " java.util.Collections.unmodifiableList(result.$name$_);\n" - "}\n"); + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, - "add$capitalized_name$(input.read$capitalized_type$());\n"); + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ = new java.util.ArrayList<$boxed_type$>();\n" + " $set_mutable_bit_parser$;\n" + "}\n" + "$name$_.add(input.read$capitalized_type$());\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateParsingCodeFromPacked(io::Printer* printer) const { printer->Print(variables_, "int length = input.readRawVarint32();\n" "int limit = input.pushLimit(length);\n" + "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" + " $name$_ = new java.util.ArrayList<$boxed_type$>();\n" + " $set_mutable_bit_parser$;\n" + "}\n" "while (input.getBytesUntilLimit() > 0) {\n" - " add$capitalized_name$(input.read$capitalized_type$());\n" + " $name$_.add(input.read$capitalized_type$());\n" "}\n" "input.popLimit(limit);\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_mutable_bit_parser$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); +} + +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { if (descriptor_->options().packed()) { printer->Print(variables_, @@ -401,18 +797,18 @@ GenerateSerializationCode(io::Printer* printer) const { " output.writeRawVarint32($tag$);\n" " output.writeRawVarint32($name$MemoizedSerializedSize);\n" "}\n" - "for ($type$ element : get$capitalized_name$List()) {\n" - " output.write$capitalized_type$NoTag(element);\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$NoTag($name$_.get(i));\n" "}\n"); } else { printer->Print(variables_, - "for ($type$ element : get$capitalized_name$List()) {\n" - " output.write$capitalized_type$($number$, element);\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$($number$, $name$_.get(i));\n" "}\n"); } } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, "{\n" @@ -421,9 +817,9 @@ GenerateSerializedSizeCode(io::Printer* printer) const { if (FixedSize(GetType(descriptor_)) == -1) { printer->Print(variables_, - "for ($type$ element : get$capitalized_name$List()) {\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" " dataSize += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$SizeNoTag(element);\n" + " .compute$capitalized_type$SizeNoTag($name$_.get(i));\n" "}\n"); } else { printer->Print(variables_, @@ -455,7 +851,23 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print("}\n"); } -string RepeatedPrimitiveFieldGenerator::GetBoxedType() const { +void RepeatedImmutablePrimitiveFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedImmutablePrimitiveFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); +} + +string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const { return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); } diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h index 4e482a0..489e1b2 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.h +++ b/src/google/protobuf/compiler/java/java_primitive_field.h @@ -41,56 +41,115 @@ namespace google { namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } +} + +namespace protobuf { namespace compiler { namespace java { -class PrimitiveFieldGenerator : public FieldGenerator { +class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { public: - explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor); - ~PrimitiveFieldGenerator(); - - // implements FieldGenerator --------------------------------------- + explicit ImmutablePrimitiveFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutablePrimitiveFieldGenerator(); + + // implements ImmutableFieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldGenerator); }; -class RepeatedPrimitiveFieldGenerator : public FieldGenerator { +class ImmutablePrimitiveOneofFieldGenerator + : public ImmutablePrimitiveFieldGenerator { public: - explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor); - ~RepeatedPrimitiveFieldGenerator(); + ImmutablePrimitiveOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutablePrimitiveOneofFieldGenerator(); - // implements FieldGenerator --------------------------------------- + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldGenerator); +}; + +class RepeatedImmutablePrimitiveFieldGenerator + : public ImmutableFieldGenerator { + public: + explicit RepeatedImmutablePrimitiveFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + virtual ~RepeatedImmutablePrimitiveFieldGenerator(); + + // implements ImmutableFieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingCodeFromPacked(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; private: const FieldDescriptor* descriptor_; map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc index 5545bf7..aa5c523 100644 --- a/src/google/protobuf/compiler/java/java_service.cc +++ b/src/google/protobuf/compiler/java/java_service.cc @@ -33,7 +33,11 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include + +#include +#include #include +#include #include #include #include @@ -48,8 +52,18 @@ ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor) ServiceGenerator::~ServiceGenerator() {} -void ServiceGenerator::Generate(io::Printer* printer) { - bool is_own_file = descriptor_->file()->options().java_multiple_files(); +// =================================================================== +ImmutableServiceGenerator::ImmutableServiceGenerator( + const ServiceDescriptor* descriptor, Context* context) + : ServiceGenerator(descriptor), context_(context), + name_resolver_(context->GetNameResolver()) {} + +ImmutableServiceGenerator::~ImmutableServiceGenerator() {} + +void ImmutableServiceGenerator::Generate(io::Printer* printer) { + bool is_own_file = + MultipleJavaFiles(descriptor_->file(), /* immutable = */ true); + WriteServiceDocComment(printer, descriptor_); printer->Print( "public $static$ abstract class $classname$\n" " implements com.google.protobuf.Service {\n", @@ -75,7 +89,7 @@ void ServiceGenerator::Generate(io::Printer* printer) { " getDescriptor() {\n" " return $file$.getDescriptor().getServices().get($index$);\n" "}\n", - "file", ClassName(descriptor_->file()), + "file", name_resolver_->GetImmutableClassName(descriptor_->file()), "index", SimpleItoa(descriptor_->index())); GenerateGetDescriptorForType(printer); @@ -86,11 +100,18 @@ void ServiceGenerator::Generate(io::Printer* printer) { GenerateStub(printer); GenerateBlockingStub(printer); + // Add an insertion point. + printer->Print( + "\n" + "// @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); + printer->Outdent(); printer->Print("}\n\n"); } -void ServiceGenerator::GenerateGetDescriptorForType(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateGetDescriptorForType( + io::Printer* printer) { printer->Print( "public final com.google.protobuf.Descriptors.ServiceDescriptor\n" " getDescriptorForType() {\n" @@ -98,7 +119,7 @@ void ServiceGenerator::GenerateGetDescriptorForType(io::Printer* printer) { "}\n"); } -void ServiceGenerator::GenerateInterface(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateInterface(io::Printer* printer) { printer->Print("public interface Interface {\n"); printer->Indent(); GenerateAbstractMethods(printer); @@ -106,7 +127,7 @@ void ServiceGenerator::GenerateInterface(io::Printer* printer) { printer->Print("}\n\n"); } -void ServiceGenerator::GenerateNewReflectiveServiceMethod( +void ImmutableServiceGenerator::GenerateNewReflectiveServiceMethod( io::Printer* printer) { printer->Print( "public static com.google.protobuf.Service newReflectiveService(\n" @@ -118,7 +139,7 @@ void ServiceGenerator::GenerateNewReflectiveServiceMethod( for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - printer->Print("@Override\n"); + printer->Print("@java.lang.Override\n"); GenerateMethodSignature(printer, method, IS_CONCRETE); printer->Print( " {\n" @@ -133,7 +154,7 @@ void ServiceGenerator::GenerateNewReflectiveServiceMethod( printer->Print("}\n\n"); } -void ServiceGenerator::GenerateNewReflectiveBlockingServiceMethod( +void ImmutableServiceGenerator::GenerateNewReflectiveBlockingServiceMethod( io::Printer* printer) { printer->Print( "public static com.google.protobuf.BlockingService\n" @@ -154,15 +175,16 @@ void ServiceGenerator::GenerateNewReflectiveBlockingServiceMethod( printer->Print("}\n\n"); } -void ServiceGenerator::GenerateAbstractMethods(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateAbstractMethods(io::Printer* printer) { for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); + WriteMethodDocComment(printer, method); GenerateMethodSignature(printer, method, IS_ABSTRACT); printer->Print(";\n\n"); } } -void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) { printer->Print( "\n" "public final void callMethod(\n" @@ -185,8 +207,10 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { map vars; vars["index"] = SimpleItoa(i); vars["method"] = UnderscoresToCamelCase(method); - vars["input"] = ClassName(method->input_type()); - vars["output"] = ClassName(method->output_type()); + vars["input"] = name_resolver_->GetImmutableClassName( + method->input_type()); + vars["output"] = name_resolver_->GetImmutableClassName( + method->output_type()); printer->Print(vars, "case $index$:\n" " this.$method$(controller, ($input$)request,\n" @@ -208,7 +232,8 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { "\n"); } -void ServiceGenerator::GenerateCallBlockingMethod(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateCallBlockingMethod( + io::Printer* printer) { printer->Print( "\n" "public final com.google.protobuf.Message callBlockingMethod(\n" @@ -230,8 +255,10 @@ void ServiceGenerator::GenerateCallBlockingMethod(io::Printer* printer) { map vars; vars["index"] = SimpleItoa(i); vars["method"] = UnderscoresToCamelCase(method); - vars["input"] = ClassName(method->input_type()); - vars["output"] = ClassName(method->output_type()); + vars["input"] = name_resolver_->GetImmutableClassName( + method->input_type()); + vars["output"] = name_resolver_->GetImmutableClassName( + method->output_type()); printer->Print(vars, "case $index$:\n" " return impl.$method$(controller, ($input$)request);\n"); @@ -250,7 +277,7 @@ void ServiceGenerator::GenerateCallBlockingMethod(io::Printer* printer) { "\n"); } -void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, +void ImmutableServiceGenerator::GenerateGetPrototype(RequestOrResponse which, io::Printer* printer) { /* * TODO(cpovirk): The exception message says "Service.foo" when it may be @@ -274,7 +301,7 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, const MethodDescriptor* method = descriptor_->method(i); map vars; vars["index"] = SimpleItoa(i); - vars["type"] = ClassName( + vars["type"] = name_resolver_->GetImmutableClassName( (which == REQUEST) ? method->input_type() : method->output_type()); printer->Print(vars, "case $index$:\n" @@ -294,7 +321,7 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, "\n"); } -void ServiceGenerator::GenerateStub(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) { printer->Print( "public static Stub newStub(\n" " com.google.protobuf.RpcChannel channel) {\n" @@ -303,7 +330,7 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) { "\n" "public static final class Stub extends $classname$ implements Interface {" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Indent(); printer->Print( @@ -326,7 +353,8 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) { map vars; vars["index"] = SimpleItoa(i); - vars["output"] = ClassName(method->output_type()); + vars["output"] = name_resolver_->GetImmutableClassName( + method->output_type()); printer->Print(vars, "channel.callMethod(\n" " getDescriptor().getMethods().get($index$),\n" @@ -348,7 +376,7 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) { "\n"); } -void ServiceGenerator::GenerateBlockingStub(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) { printer->Print( "public static BlockingInterface newBlockingStub(\n" " com.google.protobuf.BlockingRpcChannel channel) {\n" @@ -390,7 +418,8 @@ void ServiceGenerator::GenerateBlockingStub(io::Printer* printer) { map vars; vars["index"] = SimpleItoa(i); - vars["output"] = ClassName(method->output_type()); + vars["output"] = name_resolver_->GetImmutableClassName( + method->output_type()); printer->Print(vars, "return ($output$) channel.callBlockingMethod(\n" " getDescriptor().getMethods().get($index$),\n" @@ -408,13 +437,13 @@ void ServiceGenerator::GenerateBlockingStub(io::Printer* printer) { printer->Print("}\n"); } -void ServiceGenerator::GenerateMethodSignature(io::Printer* printer, +void ImmutableServiceGenerator::GenerateMethodSignature(io::Printer* printer, const MethodDescriptor* method, IsAbstract is_abstract) { map vars; vars["name"] = UnderscoresToCamelCase(method); - vars["input"] = ClassName(method->input_type()); - vars["output"] = ClassName(method->output_type()); + vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); + vars["output"] = name_resolver_->GetImmutableClassName(method->output_type()); vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : ""; printer->Print(vars, "public $abstract$ void $name$(\n" @@ -423,13 +452,13 @@ void ServiceGenerator::GenerateMethodSignature(io::Printer* printer, " com.google.protobuf.RpcCallback<$output$> done)"); } -void ServiceGenerator::GenerateBlockingMethodSignature( +void ImmutableServiceGenerator::GenerateBlockingMethodSignature( io::Printer* printer, const MethodDescriptor* method) { map vars; vars["method"] = UnderscoresToCamelCase(method); - vars["input"] = ClassName(method->input_type()); - vars["output"] = ClassName(method->output_type()); + vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); + vars["output"] = name_resolver_->GetImmutableClassName(method->output_type()); printer->Print(vars, "\n" "public $output$ $method$(\n" diff --git a/src/google/protobuf/compiler/java/java_service.h b/src/google/protobuf/compiler/java/java_service.h index e07eebf..0d52325 100644 --- a/src/google/protobuf/compiler/java/java_service.h +++ b/src/google/protobuf/compiler/java/java_service.h @@ -40,8 +40,14 @@ namespace google { namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } namespace io { - class Printer; // printer.h + class Printer; // printer.h } } @@ -52,9 +58,27 @@ namespace java { class ServiceGenerator { public: explicit ServiceGenerator(const ServiceDescriptor* descriptor); - ~ServiceGenerator(); + virtual ~ServiceGenerator(); + + virtual void Generate(io::Printer* printer) = 0; + + enum RequestOrResponse { REQUEST, RESPONSE }; + enum IsAbstract { IS_ABSTRACT, IS_CONCRETE }; + + protected: + const ServiceDescriptor* descriptor_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator); +}; - void Generate(io::Printer* printer); +class ImmutableServiceGenerator : public ServiceGenerator { + public: + explicit ImmutableServiceGenerator(const ServiceDescriptor* descriptor, + Context* context); + virtual ~ImmutableServiceGenerator(); + + virtual void Generate(io::Printer* printer); private: @@ -80,7 +104,6 @@ class ServiceGenerator { void GenerateCallBlockingMethod(io::Printer* printer); // Generate the implementations of Service.get{Request,Response}Prototype(). - enum RequestOrResponse { REQUEST, RESPONSE }; void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer); // Generate a stub implementation of the service. @@ -88,7 +111,6 @@ class ServiceGenerator { // Generate a method signature, possibly abstract, without body or trailing // semicolon. - enum IsAbstract { IS_ABSTRACT, IS_CONCRETE }; void GenerateMethodSignature(io::Printer* printer, const MethodDescriptor* method, IsAbstract is_abstract); @@ -100,9 +122,9 @@ class ServiceGenerator { void GenerateBlockingMethodSignature(io::Printer* printer, const MethodDescriptor* method); - const ServiceDescriptor* descriptor_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator); + Context* context_; + ClassNameResolver* name_resolver_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableServiceGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc new file mode 100644 index 0000000..183b0ce --- /dev/null +++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc @@ -0,0 +1,201 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: xiaofeng@google.com (Feng Xiao) + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file) + : name_resolver_(new ClassNameResolver), file_(file) { +} + +SharedCodeGenerator::~SharedCodeGenerator() { +} + +void SharedCodeGenerator::Generate(GeneratorContext* context, + vector* file_list) { + string java_package = FileJavaPackage(file_); + string package_dir = JavaPackageToDir(java_package); + + if (HasDescriptorMethods(file_)) { + // Generate descriptors. + string classname = name_resolver_->GetDescriptorClassName(file_); + string filename = package_dir + classname + ".java"; + file_list->push_back(filename); + scoped_ptr output(context->Open(filename)); + scoped_ptr printer(new io::Printer(output.get(), '$')); + + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n", + "filename", file_->name()); + if (!java_package.empty()) { + printer->Print( + "package $package$;\n" + "\n", + "package", java_package); + } + printer->Print( + "public final class $classname$ {\n" + " public static com.google.protobuf.Descriptors.FileDescriptor\n" + " descriptor;\n" + " static {\n", + "classname", classname); + printer->Indent(); + printer->Indent(); + GenerateDescriptors(printer.get()); + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" + "}\n"); + + printer.reset(); + output.reset(); + } +} + + +void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { + // Embed the descriptor. We simply serialize the entire FileDescriptorProto + // and embed it as a string literal, which is parsed and built into real + // descriptors at initialization time. We unfortunately have to put it in + // a string literal, not a byte array, because apparently using a literal + // byte array causes the Java compiler to generate *instructions* to + // initialize each and every byte of the array, e.g. as if you typed: + // b[0] = 123; b[1] = 456; b[2] = 789; + // This makes huge bytecode files and can easily hit the compiler's internal + // code size limits (error "code to large"). String literals are apparently + // embedded raw, which is what we want. + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + + + string file_data; + file_proto.SerializeToString(&file_data); + + printer->Print( + "java.lang.String[] descriptorData = {\n"); + printer->Indent(); + + // Only write 40 bytes per line. + static const int kBytesPerLine = 40; + for (int i = 0; i < file_data.size(); i += kBytesPerLine) { + if (i > 0) { + // Every 400 lines, start a new string literal, in order to avoid the + // 64k length limit. + if (i % 400 == 0) { + printer->Print(",\n"); + } else { + printer->Print(" +\n"); + } + } + printer->Print("\"$data$\"", + "data", CEscape(file_data.substr(i, kBytesPerLine))); + } + + printer->Outdent(); + printer->Print("\n};\n"); + + // ----------------------------------------------------------------- + // Create the InternalDescriptorAssigner. + + printer->Print( + "com.google.protobuf.Descriptors.FileDescriptor." + "InternalDescriptorAssigner assigner =\n" + " new com.google.protobuf.Descriptors.FileDescriptor." + " InternalDescriptorAssigner() {\n" + " public com.google.protobuf.ExtensionRegistry assignDescriptors(\n" + " com.google.protobuf.Descriptors.FileDescriptor root) {\n" + " descriptor = root;\n" + // Custom options will be handled when immutable messages' outer class is + // loaded. Here we just return null and let custom options be unknown + // fields. + " return null;\n" + " }\n" + " };\n"); + + // ----------------------------------------------------------------- + // Find out all dependencies. + vector > dependencies; + for (int i = 0; i < file_->dependency_count(); i++) { + if (ShouldIncludeDependency(file_->dependency(i))) { + string filename = file_->dependency(i)->name(); + string classname = FileJavaPackage(file_->dependency(i)) + "." + + name_resolver_->GetDescriptorClassName( + file_->dependency(i)); + dependencies.push_back(make_pair(filename, classname)); + } + } + + // ----------------------------------------------------------------- + // Invoke internalBuildGeneratedFileFrom() to build the file. + printer->Print( + "com.google.protobuf.Descriptors.FileDescriptor\n" + " .internalBuildGeneratedFileFrom(descriptorData,\n" + " new com.google.protobuf.Descriptors.FileDescriptor[] {\n"); + + for (int i = 0; i < dependencies.size(); i++) { + const string& dependency = dependencies[i].second; + printer->Print( + " $dependency$.getDescriptor(),\n", + "dependency", dependency); + } + + printer->Print( + " }, assigner);\n"); +} + +bool SharedCodeGenerator::ShouldIncludeDependency( + const FileDescriptor* descriptor) { + return true; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.h b/src/google/protobuf/compiler/java/java_shared_code_generator.h new file mode 100644 index 0000000..8e37eaf --- /dev/null +++ b/src/google/protobuf/compiler/java/java_shared_code_generator.h @@ -0,0 +1,90 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: xiaofeng@google.com (Feng Xiao) +// +// Generators that generate shared code between immutable API and mutable API. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__ + +#include +#include +#include + +#include + +namespace google { +namespace protobuf { + class FileDescriptor; // descriptor.h + namespace compiler { + class GeneratorContext; // code_generator.h + namespace java { + class ClassNameResolver; // name_resolver.h + } + } + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +// A generator that generates code that are shared between immutable API +// and mutable API. Currently only descriptors are shared. +class SharedCodeGenerator { + public: + explicit SharedCodeGenerator(const FileDescriptor* file); + ~SharedCodeGenerator(); + + void Generate(GeneratorContext* generator_context, + vector* file_list); + void GenerateDescriptors(io::Printer* printer); + + private: + // Returns whether the dependency should be included in the output file. + // Always returns true for opensource, but used internally at Google to help + // improve compatibility with version 1 of protocol buffers. + bool ShouldIncludeDependency(const FileDescriptor* descriptor); + + scoped_ptr name_resolver_; + const FileDescriptor* file_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator); +}; + + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc new file mode 100644 index 0000000..374e1d4 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -0,0 +1,1056 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Author: jonp@google.com (Jon Perlow) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { + +void SetPrimitiveVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, + map* variables) { + SetCommonFieldVariables(descriptor, info, variables); + + (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY"; + + (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["default_init"] = + "= " + ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["capitalized_type"] = "String"; + (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); + (*variables)["tag_size"] = SimpleItoa( + WireFormat::TagSize(descriptor->number(), GetType(descriptor))); + (*variables)["null_check"] = + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n"; + + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + if (SupportFieldPresence(descriptor->file())) { + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_message"] = + GenerateSetBit(messageBitIndex) + ";"; + (*variables)["set_has_field_bit_builder"] = + GenerateSetBit(builderBitIndex) + ";"; + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex) + ";"; + + (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + } else { + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["set_has_field_bit_builder"] = ""; + (*variables)["clear_has_field_bit_builder"] = ""; + + (*variables)["is_field_present_message"] = + "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()"; + } + + // For repeated builders, one bit is used for whether the array is immutable. + (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); + + // For repeated fields, one bit is used for whether the array is immutable + // in the parsing constructor. + (*variables)["get_mutable_bit_parser"] = + GenerateGetBitMutableLocal(builderBitIndex); + (*variables)["set_mutable_bit_parser"] = + GenerateSetBitMutableLocal(builderBitIndex); + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); +} + +bool CheckUtf8(const FieldDescriptor* descriptor) { + return descriptor->file()->options().java_string_check_utf8(); +} + +} // namespace + +// =================================================================== + +ImmutableStringFieldGenerator:: +ImmutableStringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {} + +int ImmutableStringFieldGenerator::GetNumBitsForMessage() const { + return 1; +} + +int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +// A note about how strings are handled. This code used to just store a String +// in the Message. This had two issues: +// +// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded +// strings, but rather fields that were raw bytes incorrectly marked +// as strings in the proto file. This is common because in the proto1 +// syntax, string was the way to indicate bytes and C++ engineers can +// easily make this mistake without affecting the C++ API. By converting to +// strings immediately, some java code might corrupt these byte arrays as +// it passes through a java server even if the field was never accessed by +// application code. +// +// 2. There's a performance hit to converting between bytes and strings and +// it many cases, the field is never even read by the application code. This +// avoids unnecessary conversions in the common use cases. +// +// So now, the field for String is maintained as an Object reference which can +// either store a String or a ByteString. The code uses an instanceof check +// to see which one it has and converts to the other one if needed. It remembers +// the last value requested (in a thread safe manner) as this is most likely +// the one needed next. The thread safety is such that if two threads both +// convert the field because the changes made by each thread were not visible to +// the other, they may cause a conversion to happen more times than would +// otherwise be necessary. This was deemed better than adding synchronization +// overhead. It will not cause any corruption issues or affect the behavior of +// the API. The instanceof check is also highly optimized in the JVM and we +// decided it was better to reduce the memory overhead by not having two +// separate fields but rather use dynamic type checking. +// +// For single fields, the logic for this is done inside the generated code. For +// repeated fields, the logic is done in LazyStringArrayList and +// UnmodifiableLazyStringList. +void ImmutableStringFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.lang.String get$capitalized_name$();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes();\n"); +} + +void ImmutableStringFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private java.lang.Object $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$() {\n" + " java.lang.Object ref = $name$_;\n" + " if (ref instanceof java.lang.String) {\n" + " return (java.lang.String) ref;\n" + " } else {\n" + " com.google.protobuf.ByteString bs = \n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " $name$_ = s;\n"); + } else { + printer->Print(variables_, + " if (bs.isValidUtf8()) {\n" + " $name$_ = s;\n" + " }\n"); + } + printer->Print(variables_, + " return s;\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes() {\n" + " java.lang.Object ref = $name$_;\n" + " if (ref instanceof java.lang.String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " $name$_ = b;\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); +} + +void ImmutableStringFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + printer->Print(variables_, + "private java.lang.Object $name$_ $default_init$;\n"); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$() {\n" + " java.lang.Object ref = $name$_;\n" + " if (!(ref instanceof java.lang.String)) {\n" + " com.google.protobuf.ByteString bs =\n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " $name$_ = s;\n"); + } else { + printer->Print(variables_, + " if (bs.isValidUtf8()) {\n" + " $name$_ = s;\n" + " }\n"); + } + printer->Print(variables_, + " return s;\n" + " } else {\n" + " return (java.lang.String) ref;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes() {\n" + " java.lang.Object ref = $name$_;\n" + " if (ref instanceof String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " $name$_ = b;\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " java.lang.String value) {\n" + "$null_check$" + " $set_has_field_bit_builder$\n" + " $name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $clear_has_field_bit_builder$\n"); + // The default value is not a simple literal so we want to avoid executing + // it multiple times. Instead, get the default out of the default instance. + printer->Print(variables_, + " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); + printer->Print(variables_, + " $on_changed$\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n" + "$null_check$"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " checkByteStringIsUtf8(value);\n"); + } + printer->Print(variables_, + " $set_has_field_bit_builder$\n" + " $name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); +} + +void ImmutableStringFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + +void ImmutableStringFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default$;\n"); +} + +void ImmutableStringFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $default$;\n" + "$clear_has_field_bit_builder$\n"); +} + +void ImmutableStringFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + // Allow a slight breach of abstraction here in order to avoid forcing + // all string fields to Strings when copying fields from a Message. + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " $set_has_field_bit_builder$\n" + " $name$_ = other.$name$_;\n" + " $on_changed$\n" + "}\n"); + } else { + printer->Print(variables_, + "if (!other.get$capitalized_name$().isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $on_changed$\n" + "}\n"); + } +} + +void ImmutableStringFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); + } + printer->Print(variables_, + "result.$name$_ = $name$_;\n"); +} + +void ImmutableStringFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + "String s = input.readStringRequireUtf8();\n" + "$set_has_field_bit_message$\n" + "$name$_ = s;\n"); + } else { + printer->Print(variables_, + "com.google.protobuf.ByteString bs = input.readBytes();\n" + "$set_has_field_bit_message$\n" + "$name$_ = bs;\n"); + } +} + +void ImmutableStringFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // noop for strings. +} + +void ImmutableStringFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_field_present_message$) {\n" + " output.writeBytes($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +void ImmutableStringFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_field_present_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +void ImmutableStringFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); +} + +void ImmutableStringFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n"); + printer->Print(variables_, + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); +} + +string ImmutableStringFieldGenerator::GetBoxedType() const { + return "java.lang.String"; +} + +// =================================================================== + +ImmutableStringOneofFieldGenerator:: +ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableStringFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); +} + +ImmutableStringOneofFieldGenerator:: +~ImmutableStringOneofFieldGenerator() {} + +void ImmutableStringOneofFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (ref instanceof java.lang.String) {\n" + " return (java.lang.String) ref;\n" + " } else {\n" + " com.google.protobuf.ByteString bs = \n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " if ($has_oneof_case_message$) {\n" + " $oneof_name$_ = s;\n" + " }\n"); + } else { + printer->Print(variables_, + " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n" + " $oneof_name$_ = s;\n" + " }\n"); + } + printer->Print(variables_, + " return s;\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (ref instanceof java.lang.String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " if ($has_oneof_case_message$) {\n" + " $oneof_name$_ = b;\n" + " }\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); +} + +void ImmutableStringOneofFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (!(ref instanceof java.lang.String)) {\n" + " com.google.protobuf.ByteString bs =\n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n" + " if ($has_oneof_case_message$) {\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " $oneof_name$_ = s;\n"); + } else { + printer->Print(variables_, + " if (bs.isValidUtf8()) {\n" + " $oneof_name$_ = s;\n" + " }\n"); + } + printer->Print(variables_, + " }\n" + " return s;\n" + " } else {\n" + " return (java.lang.String) ref;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (ref instanceof String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " if ($has_oneof_case_message$) {\n" + " $oneof_name$_ = b;\n" + " }\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " java.lang.String value) {\n" + "$null_check$" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + " }\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n" + "$null_check$"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " checkByteStringIsUtf8(value);\n"); + } + printer->Print(variables_, + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); +} + +void ImmutableStringOneofFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // Allow a slight breach of abstraction here in order to avoid forcing + // all string fields to Strings when copying fields from a Message. + printer->Print(variables_, + "$set_oneof_case_message$;\n" + "$oneof_name$_ = other.$oneof_name$_;\n" + "$on_changed$\n"); +} + +void ImmutableStringOneofFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " result.$oneof_name$_ = $oneof_name$_;\n" + "}\n"); +} + +void ImmutableStringOneofFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + "String s = input.readStringRequireUtf8();\n" + "$set_oneof_case_message$;\n" + "$oneof_name$_ = s;\n}\n"); + } else { + printer->Print(variables_, + "com.google.protobuf.ByteString bs = input.readBytes();\n" + "$set_oneof_case_message$;\n" + "$oneof_name$_ = bs;\n"); + } +} + +void ImmutableStringOneofFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.writeBytes($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +void ImmutableStringOneofFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +// =================================================================== + +RepeatedImmutableStringFieldGenerator:: +RepeatedImmutableStringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +RepeatedImmutableStringFieldGenerator:: +~RepeatedImmutableStringFieldGenerator() {} + +int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$com.google.protobuf.ProtocolStringList\n" + " get$capitalized_name$List();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes(int index);\n"); +} + + +void RepeatedImmutableStringFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private com.google.protobuf.LazyStringList $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ProtocolStringList\n" + " get$capitalized_name$List() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes(int index) {\n" + " return $name$_.getByteString(index);\n" + "}\n"); + + if (descriptor_->options().packed() && + HasGeneratedMethods(descriptor_->containing_type())) { + printer->Print(variables_, + "private int $name$MemoizedSerializedSize = -1;\n"); + } +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // One field is the list and the bit field keeps track of whether the + // list is immutable. If it's immutable, the invariant is that it must + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a refererence to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + printer->Print(variables_, + "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n"); + + printer->Print(variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n"); + + // Note: We return an unmodifiable list because otherwise the caller + // could hold on to the returned list and modify it after the message + // has been built, thus mutating the message which is supposed to be + // immutable. + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ProtocolStringList\n" + " get$capitalized_name$List() {\n" + " return $name$_.getUnmodifiableView();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes(int index) {\n" + " return $name$_.getByteString(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, java.lang.String value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$(\n" + " java.lang.String value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" + " values, $name$_);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $name$_ = $empty_list$;\n" + " $clear_mutable_bit_builder$;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n" + "$null_check$"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " checkByteStringIsUtf8(value);\n"); + } + printer->Print(variables_, + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $empty_list$;\n"); +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $empty_list$;\n" + "$clear_mutable_bit_builder$;\n"); +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations: + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. + printer->Print(variables_, + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n"); +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + // The code below ensures that the result has an immutable list. If our + // list is immutable, we can just reuse it. If not, we make it immutable. + + printer->Print(variables_, + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = $name$_.getUnmodifiableView();\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + "String s = input.readStringRequireUtf8();\n"); + } else { + printer->Print(variables_, + "com.google.protobuf.ByteString bs = input.readBytes();\n"); + } + printer->Print(variables_, + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" + " $set_mutable_bit_parser$;\n" + "}\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + "$name$_.add(s);\n"); + } else { + printer->Print(variables_, + "$name$_.add(bs);\n"); + } +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateParsingCodeFromPacked(io::Printer* printer) const { + printer->Print(variables_, + "int length = input.readRawVarint32();\n" + "int limit = input.pushLimit(length);\n" + "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" + " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" + " $set_mutable_bit_parser$;\n" + "}\n" + "while (input.getBytesUntilLimit() > 0) {\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " String s = input.readStringRequireUtf8();\n"); + } else { + printer->Print(variables_, + " String s = input.readString();\n"); + } + printer->Print(variables_, + " $name$.add(s);\n"); + printer->Print(variables_, + "}\n" + "input.popLimit(limit);\n"); +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_mutable_bit_parser$) {\n" + " $name$_ = $name$_.getUnmodifiableView();\n" + "}\n"); +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (get$capitalized_name$List().size() > 0) {\n" + " output.writeRawVarint32($tag$);\n" + " output.writeRawVarint32($name$MemoizedSerializedSize);\n" + "}\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$NoTag($name$_.get(i));\n" + "}\n"); + } else { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeBytes($number$, $name$_.getByteString(i));\n" + "}\n"); + } +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "{\n" + " int dataSize = 0;\n"); + printer->Indent(); + + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " dataSize += com.google.protobuf.CodedOutputStream\n" + " .computeBytesSizeNoTag($name$_.getByteString(i));\n" + "}\n"); + + printer->Print( + "size += dataSize;\n"); + + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (!get$capitalized_name$List().isEmpty()) {\n" + " size += $tag_size$;\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeInt32SizeNoTag(dataSize);\n" + "}\n"); + } else { + printer->Print(variables_, + "size += $tag_size$ * get$capitalized_name$List().size();\n"); + } + + // cache the data size for packed fields. + if (descriptor_->options().packed()) { + printer->Print(variables_, + "$name$MemoizedSerializedSize = dataSize;\n"); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedImmutableStringFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); +} + +string RepeatedImmutableStringFieldGenerator::GetBoxedType() const { + return "String"; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_string_field.h b/src/google/protobuf/compiler/java/java_string_field.h new file mode 100644 index 0000000..348cbcb --- /dev/null +++ b/src/google/protobuf/compiler/java/java_string_field.h @@ -0,0 +1,160 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Author: jonp@google.com (Jon Perlow) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { + public: + explicit ImmutableStringFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableStringFieldGenerator(); + + // implements ImmutableFieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + protected: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldGenerator); +}; + +class ImmutableStringOneofFieldGenerator + : public ImmutableStringFieldGenerator { + public: + ImmutableStringOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableStringOneofFieldGenerator(); + + private: + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldGenerator); +}; + +class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator { + public: + explicit RepeatedImmutableStringFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~RepeatedImmutableStringFieldGenerator(); + + // implements ImmutableFieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingCodeFromPacked(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ diff --git a/src/google/protobuf/compiler/javamicro/javamicro_file.h b/src/google/protobuf/compiler/javamicro/javamicro_file.h index 430172a..1804abf 100644 --- a/src/google/protobuf/compiler/javamicro/javamicro_file.h +++ b/src/google/protobuf/compiler/javamicro/javamicro_file.h @@ -38,6 +38,7 @@ #include #include #include +#include #include namespace google { @@ -46,9 +47,6 @@ namespace protobuf { namespace io { class Printer; // printer.h } - namespace compiler { - class OutputDirectory; // code_generator.h - } } namespace protobuf { diff --git a/src/google/protobuf/compiler/javanano/javanano_file.h b/src/google/protobuf/compiler/javanano/javanano_file.h index 9472721..cfcd7c6 100644 --- a/src/google/protobuf/compiler/javanano/javanano_file.h +++ b/src/google/protobuf/compiler/javanano/javanano_file.h @@ -38,6 +38,7 @@ #include #include #include +#include #include namespace google { @@ -46,9 +47,6 @@ namespace protobuf { namespace io { class Printer; // printer.h } - namespace compiler { - class OutputDirectory; // code_generator.h - } } namespace protobuf { diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc index 8bd71b1..ed5b6a7 100644 --- a/src/google/protobuf/compiler/main.cc +++ b/src/google/protobuf/compiler/main.cc @@ -45,7 +45,7 @@ int main(int argc, char* argv[]) { // Proto2 C++ google::protobuf::compiler::cpp::CppGenerator cpp_generator; - cli.RegisterGenerator("--cpp_out", &cpp_generator, + cli.RegisterGenerator("--cpp_out", "--cpp_opt", &cpp_generator, "Generate C++ header and source."); // Proto2 Java diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index 83d5a4e..1f91817 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -32,19 +32,32 @@ #include +#include + #include +#include #include #include #include #include #include #include -#include +#include namespace google { namespace protobuf { namespace compiler { +// Returns the list of the names of files in all_files in the form of a +// comma-separated string. +string CommaSeparatedList(const vector all_files) { + vector names; + for (int i = 0; i < all_files.size(); i++) { + names.push_back(all_files[i]->name()); + } + return Join(names, ","); +} + static const char* kFirstInsertionPointName = "first_mock_insertion_point"; static const char* kSecondInsertionPointName = "second_mock_insertion_point"; static const char* kFirstInsertionPoint = @@ -63,13 +76,14 @@ void MockCodeGenerator::ExpectGenerated( const string& insertions, const string& file, const string& first_message_name, + const string& first_parsed_file_name, const string& output_directory) { string content; - ASSERT_TRUE(File::ReadFileToString( - output_directory + "/" + GetOutputFileName(name, file), &content)); + GOOGLE_CHECK_OK( + File::GetContents(output_directory + "/" + GetOutputFileName(name, file), + &content, true)); - vector lines; - SplitStringUsing(content, "\n", &lines); + vector lines = Split(content, "\n", true); while (!lines.empty() && lines.back().empty()) { lines.pop_back(); @@ -83,8 +97,9 @@ void MockCodeGenerator::ExpectGenerated( SplitStringUsing(insertions, ",", &insertion_list); } - ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2); - EXPECT_EQ(GetOutputFileContent(name, parameter, file, first_message_name), + EXPECT_EQ(lines.size(), 3 + insertion_list.size() * 2); + EXPECT_EQ(GetOutputFileContent(name, parameter, file, + first_parsed_file_name, first_message_name), lines[0]); EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]); @@ -92,12 +107,12 @@ void MockCodeGenerator::ExpectGenerated( for (int i = 0; i < insertion_list.size(); i++) { EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert", - file, first_message_name), + file, file, first_message_name), lines[1 + i]); // Second insertion point is indented, so the inserted text should // automatically be indented too. EXPECT_EQ(" " + GetOutputFileContent(insertion_list[i], "second_insert", - file, first_message_name), + file, file, first_message_name), lines[2 + insertion_list.size() + i]); } } @@ -105,7 +120,7 @@ void MockCodeGenerator::ExpectGenerated( bool MockCodeGenerator::Generate( const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { for (int i = 0; i < file->message_type_count(); i++) { if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) { @@ -120,6 +135,15 @@ bool MockCodeGenerator::Generate( } else if (command == "Abort") { cerr << "Saw message type MockCodeGenerator_Abort." << endl; abort(); + } else if (command == "HasSourceCodeInfo") { + FileDescriptorProto file_descriptor_proto; + file->CopySourceCodeInfoTo(&file_descriptor_proto); + bool has_source_code_info = + file_descriptor_proto.has_source_code_info() && + file_descriptor_proto.source_code_info().location_size() > 0; + cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: " + << has_source_code_info << "." << endl; + abort(); } else { GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command; } @@ -133,12 +157,11 @@ bool MockCodeGenerator::Generate( for (int i = 0; i < insert_into.size(); i++) { { - scoped_ptr output( - output_directory->OpenForInsert( - GetOutputFileName(insert_into[i], file), - kFirstInsertionPointName)); + scoped_ptr output(context->OpenForInsert( + GetOutputFileName(insert_into[i], file), kFirstInsertionPointName)); io::Printer printer(output.get(), '$'); - printer.PrintRaw(GetOutputFileContent(name_, "first_insert", file)); + printer.PrintRaw(GetOutputFileContent(name_, "first_insert", + file, context)); if (printer.failed()) { *error = "MockCodeGenerator detected write error."; return false; @@ -147,11 +170,11 @@ bool MockCodeGenerator::Generate( { scoped_ptr output( - output_directory->OpenForInsert( - GetOutputFileName(insert_into[i], file), - kSecondInsertionPointName)); + context->OpenForInsert(GetOutputFileName(insert_into[i], file), + kSecondInsertionPointName)); io::Printer printer(output.get(), '$'); - printer.PrintRaw(GetOutputFileContent(name_, "second_insert", file)); + printer.PrintRaw(GetOutputFileContent(name_, "second_insert", + file, context)); if (printer.failed()) { *error = "MockCodeGenerator detected write error."; return false; @@ -160,10 +183,11 @@ bool MockCodeGenerator::Generate( } } else { scoped_ptr output( - output_directory->Open(GetOutputFileName(name_, file))); + context->Open(GetOutputFileName(name_, file))); io::Printer printer(output.get(), '$'); - printer.PrintRaw(GetOutputFileContent(name_, parameter, file)); + printer.PrintRaw(GetOutputFileContent(name_, parameter, + file, context)); printer.PrintRaw(kFirstInsertionPoint); printer.PrintRaw(kSecondInsertionPoint); @@ -186,11 +210,16 @@ string MockCodeGenerator::GetOutputFileName(const string& generator_name, return file + ".MockCodeGenerator." + generator_name; } -string MockCodeGenerator::GetOutputFileContent(const string& generator_name, - const string& parameter, - const FileDescriptor* file) { +string MockCodeGenerator::GetOutputFileContent( + const string& generator_name, + const string& parameter, + const FileDescriptor* file, + GeneratorContext *context) { + vector all_files; + context->ListParsedFiles(&all_files); return GetOutputFileContent( generator_name, parameter, file->name(), + CommaSeparatedList(all_files), file->message_type_count() > 0 ? file->message_type(0)->name() : "(none)"); } @@ -199,9 +228,11 @@ string MockCodeGenerator::GetOutputFileContent( const string& generator_name, const string& parameter, const string& file, + const string& parsed_file_list, const string& first_message_name) { - return strings::Substitute("$0: $1, $2, $3\n", - generator_name, parameter, file, first_message_name); + return strings::Substitute("$0: $1, $2, $3, $4\n", + generator_name, parameter, file, + first_message_name, parsed_file_list); } } // namespace compiler diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h index 01d69dd..506fd20 100644 --- a/src/google/protobuf/compiler/mock_code_generator.h +++ b/src/google/protobuf/compiler/mock_code_generator.h @@ -59,6 +59,10 @@ namespace compiler { // MockCodeGenerator_Exit." to stderr and then calls exit(123). // MockCodeGenerator_Abort: Generate() prints "Saw message type // MockCodeGenerator_Abort." to stderr and then calls abort(). +// MockCodeGenerator_HasSourceCodeInfo: Causes Generate() to abort after +// printing "Saw message type MockCodeGenerator_HasSourceCodeInfo: FOO." to +// stderr, where FOO is "1" if the supplied FileDescriptorProto has source +// code info, and "0" otherwise. class MockCodeGenerator : public CodeGenerator { public: MockCodeGenerator(const string& name); @@ -69,11 +73,14 @@ class MockCodeGenerator : public CodeGenerator { // // |insertions| is a comma-separated list of names of MockCodeGenerators which // should have inserted lines into this file. + // |parsed_file_list| is a comma-separated list of names of the files + // that are being compiled together in this run. static void ExpectGenerated(const string& name, const string& parameter, const string& insertions, const string& file, const string& first_message_name, + const string& parsed_file_list, const string& output_directory); // Get the name of the file which would be written by the given generator. @@ -86,7 +93,7 @@ class MockCodeGenerator : public CodeGenerator { virtual bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const; private: @@ -94,10 +101,12 @@ class MockCodeGenerator : public CodeGenerator { static string GetOutputFileContent(const string& generator_name, const string& parameter, - const FileDescriptor* file); + const FileDescriptor* file, + GeneratorContext *context); static string GetOutputFileContent(const string& generator_name, const string& parameter, const string& file, + const string& parsed_file_list, const string& first_message_name); }; diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index 758f70d..7e0df7e 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -46,7 +46,7 @@ #include #include #include -#include +#include namespace google { namespace protobuf { @@ -174,6 +174,20 @@ bool Parser::ConsumeInteger(int* output, const char* error) { } } +bool Parser::ConsumeSignedInteger(int* output, const char* error) { + bool is_negative = false; + uint64 max_value = kint32max; + if (TryConsume("-")) { + is_negative = true; + max_value += 1; + } + uint64 value = 0; + DO(ConsumeInteger64(max_value, &value, error)); + if (is_negative) value *= -1; + *output = value; + return true; +} + bool Parser::ConsumeInteger64(uint64 max_value, uint64* output, const char* error) { if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { @@ -237,6 +251,35 @@ bool Parser::ConsumeString(string* output, const char* error) { } } +bool Parser::TryConsumeEndOfDeclaration(const char* text, + const LocationRecorder* location) { + if (LookingAt(text)) { + string leading, trailing; + input_->NextWithComments(&trailing, NULL, &leading); + + // Save the leading comments for next time, and recall the leading comments + // from last time. + leading.swap(upcoming_doc_comments_); + + if (location != NULL) { + location->AttachComments(&leading, &trailing); + } + return true; + } else { + return false; + } +} + +bool Parser::ConsumeEndOfDeclaration(const char* text, + const LocationRecorder* location) { + if (TryConsumeEndOfDeclaration(text, location)) { + return true; + } else { + AddError("Expected \"" + string(text) + "\"."); + return false; + } +} + // ------------------------------------------------------------------- void Parser::AddError(int line, int column, const string& error) { @@ -250,20 +293,87 @@ void Parser::AddError(const string& error) { AddError(input_->current().line, input_->current().column, error); } -void Parser::RecordLocation( - const Message* descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location, - int line, int column) { - if (source_location_table_ != NULL) { - source_location_table_->Add(descriptor, location, line, column); +// ------------------------------------------------------------------- + +Parser::LocationRecorder::LocationRecorder(Parser* parser) + : parser_(parser), + location_(parser_->source_code_info_->add_location()) { + location_->add_span(parser_->input_->current().line); + location_->add_span(parser_->input_->current().column); +} + +Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent) { + Init(parent); +} + +Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent, + int path1) { + Init(parent); + AddPath(path1); +} + +Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent, + int path1, int path2) { + Init(parent); + AddPath(path1); + AddPath(path2); +} + +void Parser::LocationRecorder::Init(const LocationRecorder& parent) { + parser_ = parent.parser_; + location_ = parser_->source_code_info_->add_location(); + location_->mutable_path()->CopyFrom(parent.location_->path()); + + location_->add_span(parser_->input_->current().line); + location_->add_span(parser_->input_->current().column); +} + +Parser::LocationRecorder::~LocationRecorder() { + if (location_->span_size() <= 2) { + EndAt(parser_->input_->previous()); } } -void Parser::RecordLocation( - const Message* descriptor, +void Parser::LocationRecorder::AddPath(int path_component) { + location_->add_path(path_component); +} + +void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) { + location_->set_span(0, token.line); + location_->set_span(1, token.column); +} + +void Parser::LocationRecorder::StartAt(const LocationRecorder& other) { + location_->set_span(0, other.location_->span(0)); + location_->set_span(1, other.location_->span(1)); +} + +void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) { + if (token.line != location_->span(0)) { + location_->add_span(token.line); + } + location_->add_span(token.end_column); +} + +void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor, DescriptorPool::ErrorCollector::ErrorLocation location) { - RecordLocation(descriptor, location, - input_->current().line, input_->current().column); + if (parser_->source_location_table_ != NULL) { + parser_->source_location_table_->Add( + descriptor, location, location_->span(0), location_->span(1)); + } +} + +void Parser::LocationRecorder::AttachComments( + string* leading, string* trailing) const { + GOOGLE_CHECK(!location_->has_leading_comments()); + GOOGLE_CHECK(!location_->has_trailing_comments()); + + if (!leading->empty()) { + location_->mutable_leading_comments()->swap(*leading); + } + if (!trailing->empty()) { + location_->mutable_trailing_comments()->swap(*trailing); + } } // ------------------------------------------------------------------- @@ -273,7 +383,7 @@ void Parser::SkipStatement() { if (AtEnd()) { return; } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) { - if (TryConsume(";")) { + if (TryConsumeEndOfDeclaration(";", NULL)) { return; } else if (TryConsume("{")) { SkipRestOfBlock(); @@ -291,7 +401,7 @@ void Parser::SkipRestOfBlock() { if (AtEnd()) { return; } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) { - if (TryConsume("}")) { + if (TryConsumeEndOfDeclaration("}", NULL)) { return; } else if (TryConsume("{")) { SkipRestOfBlock(); @@ -308,38 +418,51 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { had_errors_ = false; syntax_identifier_.clear(); + // Note that |file| could be NULL at this point if + // stop_after_syntax_identifier_ is true. So, we conservatively allocate + // SourceCodeInfo on the stack, then swap it into the FileDescriptorProto + // later on. + SourceCodeInfo source_code_info; + source_code_info_ = &source_code_info; + if (LookingAtType(io::Tokenizer::TYPE_START)) { // Advance to first token. - input_->Next(); + input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_); } - if (require_syntax_identifier_ || LookingAt("syntax")) { - if (!ParseSyntaxIdentifier()) { - // Don't attempt to parse the file if we didn't recognize the syntax - // identifier. - return false; + { + LocationRecorder root_location(this); + + if (require_syntax_identifier_ || LookingAt("syntax")) { + if (!ParseSyntaxIdentifier()) { + // Don't attempt to parse the file if we didn't recognize the syntax + // identifier. + return false; + } + } else if (!stop_after_syntax_identifier_) { + syntax_identifier_ = "proto2"; } - } else if (!stop_after_syntax_identifier_) { - syntax_identifier_ = "proto2"; - } - if (stop_after_syntax_identifier_) return !had_errors_; + if (stop_after_syntax_identifier_) return !had_errors_; - // Repeatedly parse statements until we reach the end of the file. - while (!AtEnd()) { - if (!ParseTopLevelStatement(file)) { - // This statement failed to parse. Skip it, but keep looping to parse - // other statements. - SkipStatement(); + // Repeatedly parse statements until we reach the end of the file. + while (!AtEnd()) { + if (!ParseTopLevelStatement(file, root_location)) { + // This statement failed to parse. Skip it, but keep looping to parse + // other statements. + SkipStatement(); - if (LookingAt("}")) { - AddError("Unmatched \"}\"."); - input_->Next(); + if (LookingAt("}")) { + AddError("Unmatched \"}\"."); + input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_); + } } } } input_ = NULL; + source_code_info_ = NULL; + source_code_info.Swap(file->mutable_source_code_info()); return !had_errors_; } @@ -349,7 +472,7 @@ bool Parser::ParseSyntaxIdentifier() { io::Tokenizer::Token syntax_token = input_->current(); string syntax; DO(ConsumeString(&syntax, "Expected syntax identifier.")); - DO(Consume(";")); + DO(ConsumeEndOfDeclaration(";", NULL)); syntax_identifier_ = syntax; @@ -363,25 +486,43 @@ bool Parser::ParseSyntaxIdentifier() { return true; } -bool Parser::ParseTopLevelStatement(FileDescriptorProto* file) { - if (TryConsume(";")) { +bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, + const LocationRecorder& root_location) { + if (TryConsumeEndOfDeclaration(";", NULL)) { // empty statement; ignore return true; } else if (LookingAt("message")) { - return ParseMessageDefinition(file->add_message_type()); + LocationRecorder location(root_location, + FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size()); + return ParseMessageDefinition(file->add_message_type(), location, file); } else if (LookingAt("enum")) { - return ParseEnumDefinition(file->add_enum_type()); + LocationRecorder location(root_location, + FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size()); + return ParseEnumDefinition(file->add_enum_type(), location, file); } else if (LookingAt("service")) { - return ParseServiceDefinition(file->add_service()); + LocationRecorder location(root_location, + FileDescriptorProto::kServiceFieldNumber, file->service_size()); + return ParseServiceDefinition(file->add_service(), location, file); } else if (LookingAt("extend")) { + LocationRecorder location(root_location, + FileDescriptorProto::kExtensionFieldNumber); return ParseExtend(file->mutable_extension(), - file->mutable_message_type()); + file->mutable_message_type(), + root_location, + FileDescriptorProto::kMessageTypeFieldNumber, + location, file); } else if (LookingAt("import")) { - return ParseImport(file->add_dependency()); + return ParseImport(file->mutable_dependency(), + file->mutable_public_dependency(), + file->mutable_weak_dependency(), + root_location, file); } else if (LookingAt("package")) { - return ParsePackage(file); + return ParsePackage(file, root_location, file); } else if (LookingAt("option")) { - return ParseOption(file->mutable_options()); + LocationRecorder location(root_location, + FileDescriptorProto::kOptionsFieldNumber); + return ParseOption(file->mutable_options(), location, file, + OPTION_STATEMENT); } else { AddError("Expected top-level statement (e.g. \"message\")."); return false; @@ -391,93 +532,234 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file) { // ------------------------------------------------------------------- // Messages -bool Parser::ParseMessageDefinition(DescriptorProto* message) { +bool Parser::ParseMessageDefinition( + DescriptorProto* message, + const LocationRecorder& message_location, + const FileDescriptorProto* containing_file) { DO(Consume("message")); - RecordLocation(message, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); - DO(ParseMessageBlock(message)); + { + LocationRecorder location(message_location, + DescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + message, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); + } + DO(ParseMessageBlock(message, message_location, containing_file)); return true; } -bool Parser::ParseMessageBlock(DescriptorProto* message) { - DO(Consume("{")); +namespace { + +const int kMaxExtensionRangeSentinel = -1; - while (!TryConsume("}")) { +bool IsMessageSetWireFormatMessage(const DescriptorProto& message) { + const MessageOptions& options = message.options(); + for (int i = 0; i < options.uninterpreted_option_size(); ++i) { + const UninterpretedOption& uninterpreted = options.uninterpreted_option(i); + if (uninterpreted.name_size() == 1 && + uninterpreted.name(0).name_part() == "message_set_wire_format" && + uninterpreted.identifier_value() == "true") { + return true; + } + } + return false; +} + +// Modifies any extension ranges that specified 'max' as the end of the +// extension range, and sets them to the type-specific maximum. The actual max +// tag number can only be determined after all options have been parsed. +void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) { + const bool is_message_set = IsMessageSetWireFormatMessage(*message); + const int max_extension_number = is_message_set ? + kint32max : + FieldDescriptor::kMaxNumber + 1; + for (int i = 0; i < message->extension_range_size(); ++i) { + if (message->extension_range(i).end() == kMaxExtensionRangeSentinel) { + message->mutable_extension_range(i)->set_end(max_extension_number); + } + } +} + +} // namespace + +bool Parser::ParseMessageBlock(DescriptorProto* message, + const LocationRecorder& message_location, + const FileDescriptorProto* containing_file) { + DO(ConsumeEndOfDeclaration("{", &message_location)); + + while (!TryConsumeEndOfDeclaration("}", NULL)) { if (AtEnd()) { AddError("Reached end of input in message definition (missing '}')."); return false; } - if (!ParseMessageStatement(message)) { + if (!ParseMessageStatement(message, message_location, containing_file)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); } } + if (message->extension_range_size() > 0) { + AdjustExtensionRangesWithMaxEndNumber(message); + } return true; } -bool Parser::ParseMessageStatement(DescriptorProto* message) { - if (TryConsume(";")) { +bool Parser::ParseMessageStatement(DescriptorProto* message, + const LocationRecorder& message_location, + const FileDescriptorProto* containing_file) { + if (TryConsumeEndOfDeclaration(";", NULL)) { // empty statement; ignore return true; } else if (LookingAt("message")) { - return ParseMessageDefinition(message->add_nested_type()); + LocationRecorder location(message_location, + DescriptorProto::kNestedTypeFieldNumber, + message->nested_type_size()); + return ParseMessageDefinition(message->add_nested_type(), location, + containing_file); } else if (LookingAt("enum")) { - return ParseEnumDefinition(message->add_enum_type()); + LocationRecorder location(message_location, + DescriptorProto::kEnumTypeFieldNumber, + message->enum_type_size()); + return ParseEnumDefinition(message->add_enum_type(), location, + containing_file); } else if (LookingAt("extensions")) { - return ParseExtensions(message); + LocationRecorder location(message_location, + DescriptorProto::kExtensionRangeFieldNumber); + return ParseExtensions(message, location, containing_file); } else if (LookingAt("extend")) { + LocationRecorder location(message_location, + DescriptorProto::kExtensionFieldNumber); return ParseExtend(message->mutable_extension(), - message->mutable_nested_type()); + message->mutable_nested_type(), + message_location, + DescriptorProto::kNestedTypeFieldNumber, + location, containing_file); } else if (LookingAt("option")) { - return ParseOption(message->mutable_options()); + LocationRecorder location(message_location, + DescriptorProto::kOptionsFieldNumber); + return ParseOption(message->mutable_options(), location, + containing_file, OPTION_STATEMENT); + } else if (LookingAt("oneof")) { + int oneof_index = message->oneof_decl_size(); + LocationRecorder oneof_location(message_location, + DescriptorProto::kOneofDeclFieldNumber, + oneof_index); + + return ParseOneof(message->add_oneof_decl(), message, + oneof_index, oneof_location, message_location, + containing_file); } else { + LocationRecorder location(message_location, + DescriptorProto::kFieldFieldNumber, + message->field_size()); return ParseMessageField(message->add_field(), - message->mutable_nested_type()); + message->mutable_nested_type(), + message_location, + DescriptorProto::kNestedTypeFieldNumber, + location, + containing_file); } } bool Parser::ParseMessageField(FieldDescriptorProto* field, - RepeatedPtrField* messages) { - // Parse label and type. - FieldDescriptorProto::Label label; - DO(ParseLabel(&label)); - field->set_label(label); - - RecordLocation(field, DescriptorPool::ErrorCollector::TYPE); - FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32; - string type_name; - DO(ParseType(&type, &type_name)); - if (type_name.empty()) { - field->set_type(type); - } else { - field->set_type_name(type_name); + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file) { + { + LocationRecorder location(field_location, + FieldDescriptorProto::kLabelFieldNumber); + FieldDescriptorProto::Label label; + DO(ParseLabel(&label, containing_file)); + field->set_label(label); + } + + return ParseMessageFieldNoLabel(field, messages, parent_location, + location_field_number_for_nested_type, + field_location, + containing_file); +} + +bool Parser::ParseMessageFieldNoLabel( + FieldDescriptorProto* field, + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file) { + // Parse type. + { + LocationRecorder location(field_location); // add path later + location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE); + + FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32; + string type_name; + DO(ParseType(&type, &type_name)); + if (type_name.empty()) { + location.AddPath(FieldDescriptorProto::kTypeFieldNumber); + field->set_type(type); + } else { + location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber); + field->set_type_name(type_name); + } } // Parse name and '='. - RecordLocation(field, DescriptorPool::ErrorCollector::NAME); io::Tokenizer::Token name_token = input_->current(); - DO(ConsumeIdentifier(field->mutable_name(), "Expected field name.")); + { + LocationRecorder location(field_location, + FieldDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(field->mutable_name(), "Expected field name.")); + } DO(Consume("=", "Missing field number.")); // Parse field number. - RecordLocation(field, DescriptorPool::ErrorCollector::NUMBER); - int number; - DO(ConsumeInteger(&number, "Expected field number.")); - field->set_number(number); + { + LocationRecorder location(field_location, + FieldDescriptorProto::kNumberFieldNumber); + location.RecordLegacyLocation( + field, DescriptorPool::ErrorCollector::NUMBER); + int number; + DO(ConsumeInteger(&number, "Expected field number.")); + field->set_number(number); + } // Parse options. - DO(ParseFieldOptions(field)); + DO(ParseFieldOptions(field, field_location, containing_file)); // Deal with groups. - if (type_name.empty() && type == FieldDescriptorProto::TYPE_GROUP) { + if (field->has_type() && field->type() == FieldDescriptorProto::TYPE_GROUP) { + // Awkward: Since a group declares both a message type and a field, we + // have to create overlapping locations. + LocationRecorder group_location(parent_location); + group_location.StartAt(field_location); + group_location.AddPath(location_field_number_for_nested_type); + group_location.AddPath(messages->size()); + DescriptorProto* group = messages->Add(); group->set_name(field->name()); + // Record name location to match the field name's location. - RecordLocation(group, DescriptorPool::ErrorCollector::NAME, - name_token.line, name_token.column); + { + LocationRecorder location(group_location, + DescriptorProto::kNameFieldNumber); + location.StartAt(name_token); + location.EndAt(name_token); + location.RecordLegacyLocation( + group, DescriptorPool::ErrorCollector::NAME); + } + + // The field's type_name also comes from the name. Confusing! + { + LocationRecorder location(field_location, + FieldDescriptorProto::kTypeNameFieldNumber); + location.StartAt(name_token); + location.EndAt(name_token); + } // As a hack for backwards-compatibility, we force the group name to start // with a capital letter and lower-case the field name. New code should @@ -490,27 +772,37 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field, field->set_type_name(group->name()); if (LookingAt("{")) { - DO(ParseMessageBlock(group)); + DO(ParseMessageBlock(group, group_location, containing_file)); } else { AddError("Missing group body."); return false; } } else { - DO(Consume(";")); + DO(ConsumeEndOfDeclaration(";", &field_location)); } return true; } -bool Parser::ParseFieldOptions(FieldDescriptorProto* field) { - if (!TryConsume("[")) return true; +bool Parser::ParseFieldOptions(FieldDescriptorProto* field, + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file) { + if (!LookingAt("[")) return true; + + LocationRecorder location(field_location, + FieldDescriptorProto::kOptionsFieldNumber); + + DO(Consume("[")); // Parse field options. do { if (LookingAt("default")) { - DO(ParseDefaultAssignment(field)); + // We intentionally pass field_location rather than location here, since + // the default value is not actually an option. + DO(ParseDefaultAssignment(field, field_location, containing_file)); } else { - DO(ParseOptionAssignment(field->mutable_options())); + DO(ParseOption(field->mutable_options(), location, + containing_file, OPTION_ASSIGNMENT)); } } while (TryConsume(",")); @@ -518,7 +810,10 @@ bool Parser::ParseFieldOptions(FieldDescriptorProto* field) { return true; } -bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) { +bool Parser::ParseDefaultAssignment( + FieldDescriptorProto* field, + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file) { if (field->has_default_value()) { AddError("Already set option \"default\"."); field->clear_default_value(); @@ -527,13 +822,24 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) { DO(Consume("default")); DO(Consume("=")); - RecordLocation(field, DescriptorPool::ErrorCollector::DEFAULT_VALUE); + LocationRecorder location(field_location, + FieldDescriptorProto::kDefaultValueFieldNumber); + location.RecordLegacyLocation( + field, DescriptorPool::ErrorCollector::DEFAULT_VALUE); string* default_value = field->mutable_default_value(); if (!field->has_type()) { // The field has a type name, but we don't know if it is a message or an - // enum yet. Assume an enum for now. - DO(ConsumeIdentifier(default_value, "Expected identifier.")); + // enum yet. (If it were a primitive type, |field| would have a type set + // already.) In this case, simply take the current string as the default + // value; we will catch the error later if it is not a valid enum value. + // (N.B. that we do not check whether the current token is an identifier: + // doing so throws strange errors when the user mistypes a primitive + // typename and we assume it's an enum. E.g.: "optional int foo = 1 [default + // = 42]". In such a case the fundamental error is really that "int" is not + // a type, not that "42" is not an identifier. See b/12533582.) + *default_value = input_->current().text; + input_->Next(); return true; } @@ -559,7 +865,8 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) { } // Parse the integer to verify that it is not out-of-range. uint64 value; - DO(ConsumeInteger64(max_value, &value, "Expected integer.")); + DO(ConsumeInteger64(max_value, &value, + "Expected integer for field default value.")); // And stringify it again. default_value->append(SimpleItoa(value)); break; @@ -581,7 +888,8 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) { } // Parse the integer to verify that it is not out-of-range. uint64 value; - DO(ConsumeInteger64(max_value, &value, "Expected integer.")); + DO(ConsumeInteger64(max_value, &value, + "Expected integer for field default value.")); // And stringify it again. default_value->append(SimpleItoa(value)); break; @@ -613,7 +921,11 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) { break; case FieldDescriptorProto::TYPE_STRING: - DO(ConsumeString(default_value, "Expected string.")); + // Note: When file opton java_string_check_utf8 is true, if a + // non-string representation (eg byte[]) is later supported, it must + // be checked for UTF-8-ness. + DO(ConsumeString(default_value, "Expected string for field default " + "value.")); break; case FieldDescriptorProto::TYPE_BYTES: @@ -622,7 +934,8 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) { break; case FieldDescriptorProto::TYPE_ENUM: - DO(ConsumeIdentifier(default_value, "Expected identifier.")); + DO(ConsumeIdentifier(default_value, "Expected enum identifier for field " + "default value.")); break; case FieldDescriptorProto::TYPE_MESSAGE: @@ -634,26 +947,36 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) { return true; } -bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option) { +bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option, + const LocationRecorder& part_location, + const FileDescriptorProto* containing_file) { UninterpretedOption::NamePart* name = uninterpreted_option->add_name(); string identifier; // We parse identifiers into this string. if (LookingAt("(")) { // This is an extension. DO(Consume("(")); - // An extension name consists of dot-separated identifiers, and may begin - // with a dot. - if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { - DO(ConsumeIdentifier(&identifier, "Expected identifier.")); - name->mutable_name_part()->append(identifier); - } - while (LookingAt(".")) { - DO(Consume(".")); - name->mutable_name_part()->append("."); - DO(ConsumeIdentifier(&identifier, "Expected identifier.")); - name->mutable_name_part()->append(identifier); + + { + LocationRecorder location( + part_location, UninterpretedOption::NamePart::kNamePartFieldNumber); + // An extension name consists of dot-separated identifiers, and may begin + // with a dot. + if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + name->mutable_name_part()->append(identifier); + } + while (LookingAt(".")) { + DO(Consume(".")); + name->mutable_name_part()->append("."); + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + name->mutable_name_part()->append(identifier); + } } + DO(Consume(")")); name->set_is_extension(true); } else { // This is a regular field. + LocationRecorder location( + part_location, UninterpretedOption::NamePart::kNamePartFieldNumber); DO(ConsumeIdentifier(&identifier, "Expected identifier.")); name->mutable_name_part()->append(identifier); name->set_is_extension(false); @@ -661,116 +984,214 @@ bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option) { return true; } +bool Parser::ParseUninterpretedBlock(string* value) { + // Note that enclosing braces are not added to *value. + // We do NOT use ConsumeEndOfStatement for this brace because it's delimiting + // an expression, not a block of statements. + DO(Consume("{")); + int brace_depth = 1; + while (!AtEnd()) { + if (LookingAt("{")) { + brace_depth++; + } else if (LookingAt("}")) { + brace_depth--; + if (brace_depth == 0) { + input_->Next(); + return true; + } + } + // TODO(sanjay): Interpret line/column numbers to preserve formatting + if (!value->empty()) value->push_back(' '); + value->append(input_->current().text); + input_->Next(); + } + AddError("Unexpected end of stream while parsing aggregate value."); + return false; +} + // We don't interpret the option here. Instead we store it in an // UninterpretedOption, to be interpreted later. -bool Parser::ParseOptionAssignment(Message* options) { +bool Parser::ParseOption(Message* options, + const LocationRecorder& options_location, + const FileDescriptorProto* containing_file, + OptionStyle style) { // Create an entry in the uninterpreted_option field. const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()-> FindFieldByName("uninterpreted_option"); GOOGLE_CHECK(uninterpreted_option_field != NULL) << "No field named \"uninterpreted_option\" in the Options proto."; + const Reflection* reflection = options->GetReflection(); + + LocationRecorder location( + options_location, uninterpreted_option_field->number(), + reflection->FieldSize(*options, uninterpreted_option_field)); + + if (style == OPTION_STATEMENT) { + DO(Consume("option")); + } + UninterpretedOption* uninterpreted_option = down_cast( options->GetReflection()->AddMessage(options, uninterpreted_option_field)); // Parse dot-separated name. - RecordLocation(uninterpreted_option, - DescriptorPool::ErrorCollector::OPTION_NAME); - - DO(ParseOptionNamePart(uninterpreted_option)); + { + LocationRecorder name_location(location, + UninterpretedOption::kNameFieldNumber); + name_location.RecordLegacyLocation( + uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_NAME); + + { + LocationRecorder part_location(name_location, + uninterpreted_option->name_size()); + DO(ParseOptionNamePart(uninterpreted_option, part_location, + containing_file)); + } - while (LookingAt(".")) { - DO(Consume(".")); - DO(ParseOptionNamePart(uninterpreted_option)); + while (LookingAt(".")) { + DO(Consume(".")); + LocationRecorder part_location(name_location, + uninterpreted_option->name_size()); + DO(ParseOptionNamePart(uninterpreted_option, part_location, + containing_file)); + } } DO(Consume("=")); - RecordLocation(uninterpreted_option, - DescriptorPool::ErrorCollector::OPTION_VALUE); + { + LocationRecorder value_location(location); + value_location.RecordLegacyLocation( + uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE); - // All values are a single token, except for negative numbers, which consist - // of a single '-' symbol, followed by a positive number. - bool is_negative = TryConsume("-"); + // All values are a single token, except for negative numbers, which consist + // of a single '-' symbol, followed by a positive number. + bool is_negative = TryConsume("-"); - switch (input_->current().type) { - case io::Tokenizer::TYPE_START: - GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read."; - return false; - - case io::Tokenizer::TYPE_END: - AddError("Unexpected end of stream while parsing option value."); - return false; + switch (input_->current().type) { + case io::Tokenizer::TYPE_START: + GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read."; + return false; - case io::Tokenizer::TYPE_IDENTIFIER: { - if (is_negative) { - AddError("Invalid '-' symbol before identifier."); + case io::Tokenizer::TYPE_END: + AddError("Unexpected end of stream while parsing option value."); return false; + + case io::Tokenizer::TYPE_IDENTIFIER: { + value_location.AddPath( + UninterpretedOption::kIdentifierValueFieldNumber); + if (is_negative) { + AddError("Invalid '-' symbol before identifier."); + return false; + } + string value; + DO(ConsumeIdentifier(&value, "Expected identifier.")); + uninterpreted_option->set_identifier_value(value); + break; } - string value; - DO(ConsumeIdentifier(&value, "Expected identifier.")); - uninterpreted_option->set_identifier_value(value); - break; - } - case io::Tokenizer::TYPE_INTEGER: { - uint64 value; - uint64 max_value = - is_negative ? static_cast(kint64max) + 1 : kuint64max; - DO(ConsumeInteger64(max_value, &value, "Expected integer.")); - if (is_negative) { - uninterpreted_option->set_negative_int_value(-value); - } else { - uninterpreted_option->set_positive_int_value(value); + case io::Tokenizer::TYPE_INTEGER: { + uint64 value; + uint64 max_value = + is_negative ? static_cast(kint64max) + 1 : kuint64max; + DO(ConsumeInteger64(max_value, &value, "Expected integer.")); + if (is_negative) { + value_location.AddPath( + UninterpretedOption::kNegativeIntValueFieldNumber); + uninterpreted_option->set_negative_int_value( + -static_cast(value)); + } else { + value_location.AddPath( + UninterpretedOption::kPositiveIntValueFieldNumber); + uninterpreted_option->set_positive_int_value(value); + } + break; } - break; - } - case io::Tokenizer::TYPE_FLOAT: { - double value; - DO(ConsumeNumber(&value, "Expected number.")); - uninterpreted_option->set_double_value(is_negative ? -value : value); - break; - } + case io::Tokenizer::TYPE_FLOAT: { + value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber); + double value; + DO(ConsumeNumber(&value, "Expected number.")); + uninterpreted_option->set_double_value(is_negative ? -value : value); + break; + } - case io::Tokenizer::TYPE_STRING: { - if (is_negative) { - AddError("Invalid '-' symbol before string."); - return false; + case io::Tokenizer::TYPE_STRING: { + value_location.AddPath(UninterpretedOption::kStringValueFieldNumber); + if (is_negative) { + AddError("Invalid '-' symbol before string."); + return false; + } + string value; + DO(ConsumeString(&value, "Expected string.")); + uninterpreted_option->set_string_value(value); + break; } - string value; - DO(ConsumeString(&value, "Expected string.")); - uninterpreted_option->set_string_value(value); - break; + + case io::Tokenizer::TYPE_SYMBOL: + if (LookingAt("{")) { + value_location.AddPath( + UninterpretedOption::kAggregateValueFieldNumber); + DO(ParseUninterpretedBlock( + uninterpreted_option->mutable_aggregate_value())); + } else { + AddError("Expected option value."); + return false; + } + break; } + } - case io::Tokenizer::TYPE_SYMBOL: - AddError("Expected option value."); - return false; + if (style == OPTION_STATEMENT) { + DO(ConsumeEndOfDeclaration(";", &location)); } + return true; } -bool Parser::ParseExtensions(DescriptorProto* message) { +bool Parser::ParseExtensions(DescriptorProto* message, + const LocationRecorder& extensions_location, + const FileDescriptorProto* containing_file) { // Parse the declaration. DO(Consume("extensions")); do { + // Note that kExtensionRangeFieldNumber was already pushed by the parent. + LocationRecorder location(extensions_location, + message->extension_range_size()); + DescriptorProto::ExtensionRange* range = message->add_extension_range(); - RecordLocation(range, DescriptorPool::ErrorCollector::NUMBER); + location.RecordLegacyLocation( + range, DescriptorPool::ErrorCollector::NUMBER); int start, end; - DO(ConsumeInteger(&start, "Expected field number range.")); + io::Tokenizer::Token start_token; + + { + LocationRecorder start_location( + location, DescriptorProto::ExtensionRange::kStartFieldNumber); + start_token = input_->current(); + DO(ConsumeInteger(&start, "Expected field number range.")); + } if (TryConsume("to")) { + LocationRecorder end_location( + location, DescriptorProto::ExtensionRange::kEndFieldNumber); if (TryConsume("max")) { - end = FieldDescriptor::kMaxNumber; + // Set to the sentinel value - 1 since we increment the value below. + // The actual value of the end of the range should be set with + // AdjustExtensionRangesWithMaxEndNumber. + end = kMaxExtensionRangeSentinel - 1; } else { DO(ConsumeInteger(&end, "Expected integer.")); } } else { + LocationRecorder end_location( + location, DescriptorProto::ExtensionRange::kEndFieldNumber); + end_location.StartAt(start_token); + end_location.EndAt(start_token); end = start; } @@ -782,24 +1203,26 @@ bool Parser::ParseExtensions(DescriptorProto* message) { range->set_end(end); } while (TryConsume(",")); - DO(Consume(";")); + DO(ConsumeEndOfDeclaration(";", &extensions_location)); return true; } bool Parser::ParseExtend(RepeatedPtrField* extensions, - RepeatedPtrField* messages) { + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& extend_location, + const FileDescriptorProto* containing_file) { DO(Consume("extend")); - // We expect to see at least one extension field defined in the extend block. - // We need to create it now so we can record the extendee's location. - FieldDescriptorProto* first_field = extensions->Add(); - // Parse the extendee type. - RecordLocation(first_field, DescriptorPool::ErrorCollector::EXTENDEE); - DO(ParseUserDefinedType(first_field->mutable_extendee())); + io::Tokenizer::Token extendee_start = input_->current(); + string extendee; + DO(ParseUserDefinedType(&extendee)); + io::Tokenizer::Token extendee_end = input_->previous(); // Parse the block. - DO(Consume("{")); + DO(ConsumeEndOfDeclaration("{", &extend_location)); bool is_first = true; @@ -809,21 +1232,92 @@ bool Parser::ParseExtend(RepeatedPtrField* extensions, return false; } - FieldDescriptorProto* field; - if (is_first) { - field = first_field; - is_first = false; - } else { - field = extensions->Add(); - field->set_extendee(first_field->extendee()); + // Note that kExtensionFieldNumber was already pushed by the parent. + LocationRecorder location(extend_location, extensions->size()); + + FieldDescriptorProto* field = extensions->Add(); + + { + LocationRecorder extendee_location( + location, FieldDescriptorProto::kExtendeeFieldNumber); + extendee_location.StartAt(extendee_start); + extendee_location.EndAt(extendee_end); + + if (is_first) { + extendee_location.RecordLegacyLocation( + field, DescriptorPool::ErrorCollector::EXTENDEE); + is_first = false; + } } - if (!ParseMessageField(field, messages)) { + field->set_extendee(extendee); + + if (!ParseMessageField(field, messages, parent_location, + location_field_number_for_nested_type, + location, + containing_file)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); } - } while(!TryConsume("}")); + } while (!TryConsumeEndOfDeclaration("}", NULL)); + + return true; +} + +bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl, + DescriptorProto* containing_type, + int oneof_index, + const LocationRecorder& oneof_location, + const LocationRecorder& containing_type_location, + const FileDescriptorProto* containing_file) { + DO(Consume("oneof")); + + { + LocationRecorder name_location(oneof_location, + OneofDescriptorProto::kNameFieldNumber); + DO(ConsumeIdentifier(oneof_decl->mutable_name(), "Expected oneof name.")); + } + + DO(ConsumeEndOfDeclaration("{", &oneof_location)); + + do { + if (AtEnd()) { + AddError("Reached end of input in oneof definition (missing '}')."); + return false; + } + + // Print a nice error if the user accidentally tries to place a label + // on an individual member of a oneof. + if (LookingAt("required") || + LookingAt("optional") || + LookingAt("repeated")) { + AddError("Fields in oneofs must not have labels (required / optional " + "/ repeated)."); + // We can continue parsing here because we understand what the user + // meant. The error report will still make parsing fail overall. + input_->Next(); + } + + LocationRecorder field_location(containing_type_location, + DescriptorProto::kFieldFieldNumber, + containing_type->field_size()); + + FieldDescriptorProto* field = containing_type->add_field(); + field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); + field->set_oneof_index(oneof_index); + + if (!ParseMessageFieldNoLabel(field, + containing_type->mutable_nested_type(), + containing_type_location, + DescriptorProto::kNestedTypeFieldNumber, + field_location, + containing_file)) { + // This statement failed to parse. Skip it, but keep looping to parse + // other statements. + SkipStatement(); + } + } while (!TryConsumeEndOfDeclaration("}", NULL)); return true; } @@ -831,24 +1325,35 @@ bool Parser::ParseExtend(RepeatedPtrField* extensions, // ------------------------------------------------------------------- // Enums -bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type) { +bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location, + const FileDescriptorProto* containing_file) { DO(Consume("enum")); - RecordLocation(enum_type, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name.")); - DO(ParseEnumBlock(enum_type)); + + { + LocationRecorder location(enum_location, + EnumDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + enum_type, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name.")); + } + + DO(ParseEnumBlock(enum_type, enum_location, containing_file)); return true; } -bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type) { - DO(Consume("{")); +bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location, + const FileDescriptorProto* containing_file) { + DO(ConsumeEndOfDeclaration("{", &enum_location)); - while (!TryConsume("}")) { + while (!TryConsumeEndOfDeclaration("}", NULL)) { if (AtEnd()) { AddError("Reached end of input in enum definition (missing '}')."); return false; } - if (!ParseEnumStatement(enum_type)) { + if (!ParseEnumStatement(enum_type, enum_location, containing_file)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -858,41 +1363,73 @@ bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type) { return true; } -bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type) { - if (TryConsume(";")) { +bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location, + const FileDescriptorProto* containing_file) { + if (TryConsumeEndOfDeclaration(";", NULL)) { // empty statement; ignore return true; } else if (LookingAt("option")) { - return ParseOption(enum_type->mutable_options()); + LocationRecorder location(enum_location, + EnumDescriptorProto::kOptionsFieldNumber); + return ParseOption(enum_type->mutable_options(), location, + containing_file, OPTION_STATEMENT); } else { - return ParseEnumConstant(enum_type->add_value()); + LocationRecorder location(enum_location, + EnumDescriptorProto::kValueFieldNumber, enum_type->value_size()); + return ParseEnumConstant(enum_type->add_value(), location, containing_file); } } -bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value) { - RecordLocation(enum_value, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(enum_value->mutable_name(), - "Expected enum constant name.")); +bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value, + const LocationRecorder& enum_value_location, + const FileDescriptorProto* containing_file) { + // Parse name. + { + LocationRecorder location(enum_value_location, + EnumValueDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + enum_value, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(enum_value->mutable_name(), + "Expected enum constant name.")); + } + DO(Consume("=", "Missing numeric value for enum constant.")); - bool is_negative = TryConsume("-"); - int number; - DO(ConsumeInteger(&number, "Expected integer.")); - if (is_negative) number *= -1; - enum_value->set_number(number); + // Parse value. + { + LocationRecorder location( + enum_value_location, EnumValueDescriptorProto::kNumberFieldNumber); + location.RecordLegacyLocation( + enum_value, DescriptorPool::ErrorCollector::NUMBER); - DO(ParseEnumConstantOptions(enum_value)); + int number; + DO(ConsumeSignedInteger(&number, "Expected integer.")); + enum_value->set_number(number); + } - DO(Consume(";")); + DO(ParseEnumConstantOptions(enum_value, enum_value_location, + containing_file)); + + DO(ConsumeEndOfDeclaration(";", &enum_value_location)); return true; } -bool Parser::ParseEnumConstantOptions(EnumValueDescriptorProto* value) { - if (!TryConsume("[")) return true; +bool Parser::ParseEnumConstantOptions( + EnumValueDescriptorProto* value, + const LocationRecorder& enum_value_location, + const FileDescriptorProto* containing_file) { + if (!LookingAt("[")) return true; + + LocationRecorder location( + enum_value_location, EnumValueDescriptorProto::kOptionsFieldNumber); + + DO(Consume("[")); do { - DO(ParseOptionAssignment(value->mutable_options())); + DO(ParseOption(value->mutable_options(), location, + containing_file, OPTION_ASSIGNMENT)); } while (TryConsume(",")); DO(Consume("]")); @@ -902,24 +1439,36 @@ bool Parser::ParseEnumConstantOptions(EnumValueDescriptorProto* value) { // ------------------------------------------------------------------- // Services -bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service) { +bool Parser::ParseServiceDefinition( + ServiceDescriptorProto* service, + const LocationRecorder& service_location, + const FileDescriptorProto* containing_file) { DO(Consume("service")); - RecordLocation(service, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(service->mutable_name(), "Expected service name.")); - DO(ParseServiceBlock(service)); + + { + LocationRecorder location(service_location, + ServiceDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + service, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(service->mutable_name(), "Expected service name.")); + } + + DO(ParseServiceBlock(service, service_location, containing_file)); return true; } -bool Parser::ParseServiceBlock(ServiceDescriptorProto* service) { - DO(Consume("{")); +bool Parser::ParseServiceBlock(ServiceDescriptorProto* service, + const LocationRecorder& service_location, + const FileDescriptorProto* containing_file) { + DO(ConsumeEndOfDeclaration("{", &service_location)); - while (!TryConsume("}")) { + while (!TryConsumeEndOfDeclaration("}", NULL)) { if (AtEnd()) { AddError("Reached end of input in service definition (missing '}')."); return false; } - if (!ParseServiceStatement(service)) { + if (!ParseServiceStatement(service, service_location, containing_file)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -929,55 +1478,98 @@ bool Parser::ParseServiceBlock(ServiceDescriptorProto* service) { return true; } -bool Parser::ParseServiceStatement(ServiceDescriptorProto* service) { - if (TryConsume(";")) { +bool Parser::ParseServiceStatement(ServiceDescriptorProto* service, + const LocationRecorder& service_location, + const FileDescriptorProto* containing_file) { + if (TryConsumeEndOfDeclaration(";", NULL)) { // empty statement; ignore return true; } else if (LookingAt("option")) { - return ParseOption(service->mutable_options()); + LocationRecorder location( + service_location, ServiceDescriptorProto::kOptionsFieldNumber); + return ParseOption(service->mutable_options(), location, + containing_file, OPTION_STATEMENT); } else { - return ParseServiceMethod(service->add_method()); + LocationRecorder location(service_location, + ServiceDescriptorProto::kMethodFieldNumber, service->method_size()); + return ParseServiceMethod(service->add_method(), location, containing_file); } } -bool Parser::ParseServiceMethod(MethodDescriptorProto* method) { +bool Parser::ParseServiceMethod(MethodDescriptorProto* method, + const LocationRecorder& method_location, + const FileDescriptorProto* containing_file) { DO(Consume("rpc")); - RecordLocation(method, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(method->mutable_name(), "Expected method name.")); + + { + LocationRecorder location(method_location, + MethodDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(method->mutable_name(), "Expected method name.")); + } // Parse input type. DO(Consume("(")); - RecordLocation(method, DescriptorPool::ErrorCollector::INPUT_TYPE); - DO(ParseUserDefinedType(method->mutable_input_type())); + { + LocationRecorder location(method_location, + MethodDescriptorProto::kInputTypeFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::INPUT_TYPE); + DO(ParseUserDefinedType(method->mutable_input_type())); + } DO(Consume(")")); // Parse output type. DO(Consume("returns")); DO(Consume("(")); - RecordLocation(method, DescriptorPool::ErrorCollector::OUTPUT_TYPE); - DO(ParseUserDefinedType(method->mutable_output_type())); + { + LocationRecorder location(method_location, + MethodDescriptorProto::kOutputTypeFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::OUTPUT_TYPE); + DO(ParseUserDefinedType(method->mutable_output_type())); + } DO(Consume(")")); - if (TryConsume("{")) { + if (LookingAt("{")) { // Options! - while (!TryConsume("}")) { - if (AtEnd()) { - AddError("Reached end of input in method options (missing '}')."); - return false; - } + DO(ParseOptions(method_location, + containing_file, + MethodDescriptorProto::kOptionsFieldNumber, + method->mutable_options())); + } else { + DO(ConsumeEndOfDeclaration(";", &method_location)); + } - if (TryConsume(";")) { - // empty statement; ignore - } else { - if (!ParseOption(method->mutable_options())) { - // This statement failed to parse. Skip it, but keep looping to - // parse other statements. - SkipStatement(); - } + return true; +} + + +bool Parser::ParseOptions(const LocationRecorder& parent_location, + const FileDescriptorProto* containing_file, + const int optionsFieldNumber, + Message* mutable_options) { + // Options! + ConsumeEndOfDeclaration("{", &parent_location); + while (!TryConsumeEndOfDeclaration("}", NULL)) { + if (AtEnd()) { + AddError("Reached end of input in method options (missing '}')."); + return false; + } + + if (TryConsumeEndOfDeclaration(";", NULL)) { + // empty statement; ignore + } else { + LocationRecorder location(parent_location, + optionsFieldNumber); + if (!ParseOption(mutable_options, location, containing_file, + OPTION_STATEMENT)) { + // This statement failed to parse. Skip it, but keep looping to + // parse other statements. + SkipStatement(); } } - } else { - DO(Consume(";")); } return true; @@ -985,7 +1577,8 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method) { // ------------------------------------------------------------------- -bool Parser::ParseLabel(FieldDescriptorProto::Label* label) { +bool Parser::ParseLabel(FieldDescriptorProto::Label* label, + const FileDescriptorProto* containing_file) { if (TryConsume("optional")) { *label = FieldDescriptorProto::LABEL_OPTIONAL; return true; @@ -1053,7 +1646,9 @@ bool Parser::ParseUserDefinedType(string* type_name) { // =================================================================== -bool Parser::ParsePackage(FileDescriptorProto* file) { +bool Parser::ParsePackage(FileDescriptorProto* file, + const LocationRecorder& root_location, + const FileDescriptorProto* containing_file) { if (file->has_package()) { AddError("Multiple package definitions."); // Don't append the new package to the old one. Just replace it. Not @@ -1063,32 +1658,57 @@ bool Parser::ParsePackage(FileDescriptorProto* file) { DO(Consume("package")); - RecordLocation(file, DescriptorPool::ErrorCollector::NAME); + { + LocationRecorder location(root_location, + FileDescriptorProto::kPackageFieldNumber); + location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::NAME); - while (true) { - string identifier; - DO(ConsumeIdentifier(&identifier, "Expected identifier.")); - file->mutable_package()->append(identifier); - if (!TryConsume(".")) break; - file->mutable_package()->append("."); + while (true) { + string identifier; + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + file->mutable_package()->append(identifier); + if (!TryConsume(".")) break; + file->mutable_package()->append("."); + } + + location.EndAt(input_->previous()); + + DO(ConsumeEndOfDeclaration(";", &location)); } - DO(Consume(";")); return true; } -bool Parser::ParseImport(string* import_filename) { +bool Parser::ParseImport(RepeatedPtrField* dependency, + RepeatedField* public_dependency, + RepeatedField* weak_dependency, + const LocationRecorder& root_location, + const FileDescriptorProto* containing_file) { DO(Consume("import")); - DO(ConsumeString(import_filename, - "Expected a string naming the file to import.")); - DO(Consume(";")); - return true; -} + if (LookingAt("public")) { + LocationRecorder location( + root_location, FileDescriptorProto::kPublicDependencyFieldNumber, + public_dependency->size()); + DO(Consume("public")); + *public_dependency->Add() = dependency->size(); + } else if (LookingAt("weak")) { + LocationRecorder location( + root_location, FileDescriptorProto::kWeakDependencyFieldNumber, + weak_dependency->size()); + DO(Consume("weak")); + *weak_dependency->Add() = dependency->size(); + } + { + LocationRecorder location(root_location, + FileDescriptorProto::kDependencyFieldNumber, + dependency->size()); + DO(ConsumeString(dependency->Add(), + "Expected a string naming the file to import.")); + + location.EndAt(input_->previous()); -bool Parser::ParseOption(Message* options) { - DO(Consume("option")); - DO(ParseOptionAssignment(options)); - DO(Consume(";")); + DO(ConsumeEndOfDeclaration(";", &location)); + } return true; } diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h index 72c96d0..6bca7fa 100644 --- a/src/google/protobuf/compiler/parser.h +++ b/src/google/protobuf/compiler/parser.h @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -74,6 +73,9 @@ class LIBPROTOBUF_EXPORT Parser { // Optional fetaures: + // DEPRECATED: New code should use the SourceCodeInfo embedded in the + // FileDescriptorProto. + // // Requests that locations of certain definitions be recorded to the given // SourceLocationTable while parsing. This can be used to look up exact line // and column numbers for errors reported by DescriptorPool during validation. @@ -82,7 +84,7 @@ class LIBPROTOBUF_EXPORT Parser { source_location_table_ = location_table; } - // Requsets that errors be recorded to the given ErrorCollector while + // Requests that errors be recorded to the given ErrorCollector while // parsing. Set to NULL (the default) to discard error messages. void RecordErrorsTo(io::ErrorCollector* error_collector) { error_collector_ = error_collector; @@ -113,6 +115,8 @@ class LIBPROTOBUF_EXPORT Parser { } private: + class LocationRecorder; + // ================================================================= // Error recovery helpers @@ -161,6 +165,8 @@ class LIBPROTOBUF_EXPORT Parser { bool ConsumeIdentifier(string* output, const char* error); // Consume an integer and store its value in "output". bool ConsumeInteger(int* output, const char* error); + // Consume a signed integer and store its value in "output". + bool ConsumeSignedInteger(int* output, const char* error); // Consume a 64-bit integer and store its value in "output". If the value // is greater than max_value, an error will be reported. bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error); @@ -170,6 +176,20 @@ class LIBPROTOBUF_EXPORT Parser { // Consume a string literal and store its (unescaped) value in "output". bool ConsumeString(string* output, const char* error); + // Consume a token representing the end of the statement. Comments between + // this token and the next will be harvested for documentation. The given + // LocationRecorder should refer to the declaration that was just parsed; + // it will be populated with these comments. + // + // TODO(kenton): The LocationRecorder is const because historically locations + // have been passed around by const reference, for no particularly good + // reason. We should probably go through and change them all to mutable + // pointer to make this more intuitive. + bool TryConsumeEndOfDeclaration(const char* text, + const LocationRecorder* location); + bool ConsumeEndOfDeclaration(const char* text, + const LocationRecorder* location); + // ----------------------------------------------------------------- // Error logging helpers @@ -180,16 +200,67 @@ class LIBPROTOBUF_EXPORT Parser { // of the current token. void AddError(const string& error); - // Record the given line and column and associate it with this descriptor - // in the SourceLocationTable. - void RecordLocation(const Message* descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location, - int line, int column); - - // Record the current line and column and associate it with this descriptor - // in the SourceLocationTable. - void RecordLocation(const Message* descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location); + // Records a location in the SourceCodeInfo.location table (see + // descriptor.proto). We use RAII to ensure that the start and end locations + // are recorded -- the constructor records the start location and the + // destructor records the end location. Since the parser is + // recursive-descent, this works out beautifully. + class LIBPROTOBUF_EXPORT LocationRecorder { + public: + // Construct the file's "root" location. + LocationRecorder(Parser* parser); + + // Construct a location that represents a declaration nested within the + // given parent. E.g. a field's location is nested within the location + // for a message type. The parent's path will be copied, so you should + // call AddPath() only to add the path components leading from the parent + // to the child (as opposed to leading from the root to the child). + LocationRecorder(const LocationRecorder& parent); + + // Convenience constructors that call AddPath() one or two times. + LocationRecorder(const LocationRecorder& parent, int path1); + LocationRecorder(const LocationRecorder& parent, int path1, int path2); + + ~LocationRecorder(); + + // Add a path component. See SourceCodeInfo.Location.path in + // descriptor.proto. + void AddPath(int path_component); + + // By default the location is considered to start at the current token at + // the time the LocationRecorder is created. StartAt() sets the start + // location to the given token instead. + void StartAt(const io::Tokenizer::Token& token); + + // Start at the same location as some other LocationRecorder. + void StartAt(const LocationRecorder& other); + + // By default the location is considered to end at the previous token at + // the time the LocationRecorder is destroyed. EndAt() sets the end + // location to the given token instead. + void EndAt(const io::Tokenizer::Token& token); + + // Records the start point of this location to the SourceLocationTable that + // was passed to RecordSourceLocationsTo(), if any. SourceLocationTable + // is an older way of keeping track of source locations which is still + // used in some places. + void RecordLegacyLocation(const Message* descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location); + + // Attaches leading and trailing comments to the location. The two strings + // will be swapped into place, so after this is called *leading and + // *trailing will be empty. + // + // TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for + // why this is const. + void AttachComments(string* leading, string* trailing) const; + + private: + Parser* parser_; + SourceCodeInfo::Location* location_; + + void Init(const LocationRecorder& parent); + }; // ================================================================= // Parsers for various language constructs @@ -210,54 +281,131 @@ class LIBPROTOBUF_EXPORT Parser { // makes logic much simpler for the caller. // Parse a top-level message, enum, service, etc. - bool ParseTopLevelStatement(FileDescriptorProto* file); + bool ParseTopLevelStatement(FileDescriptorProto* file, + const LocationRecorder& root_location); // Parse various language high-level language construrcts. - bool ParseMessageDefinition(DescriptorProto* message); - bool ParseEnumDefinition(EnumDescriptorProto* enum_type); - bool ParseServiceDefinition(ServiceDescriptorProto* service); - bool ParsePackage(FileDescriptorProto* file); - bool ParseImport(string* import_filename); - bool ParseOption(Message* options); + bool ParseMessageDefinition(DescriptorProto* message, + const LocationRecorder& message_location, + const FileDescriptorProto* containing_file); + bool ParseEnumDefinition(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location, + const FileDescriptorProto* containing_file); + bool ParseServiceDefinition(ServiceDescriptorProto* service, + const LocationRecorder& service_location, + const FileDescriptorProto* containing_file); + bool ParsePackage(FileDescriptorProto* file, + const LocationRecorder& root_location, + const FileDescriptorProto* containing_file); + bool ParseImport(RepeatedPtrField* dependency, + RepeatedField* public_dependency, + RepeatedField* weak_dependency, + const LocationRecorder& root_location, + const FileDescriptorProto* containing_file); + bool ParseOption(Message* options, + const LocationRecorder& options_location, + const FileDescriptorProto* containing_file); // These methods parse the contents of a message, enum, or service type and // add them to the given object. They consume the entire block including // the beginning and ending brace. - bool ParseMessageBlock(DescriptorProto* message); - bool ParseEnumBlock(EnumDescriptorProto* enum_type); - bool ParseServiceBlock(ServiceDescriptorProto* service); + bool ParseMessageBlock(DescriptorProto* message, + const LocationRecorder& message_location, + const FileDescriptorProto* containing_file); + bool ParseEnumBlock(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location, + const FileDescriptorProto* containing_file); + bool ParseServiceBlock(ServiceDescriptorProto* service, + const LocationRecorder& service_location, + const FileDescriptorProto* containing_file); // Parse one statement within a message, enum, or service block, inclunding // final semicolon. - bool ParseMessageStatement(DescriptorProto* message); - bool ParseEnumStatement(EnumDescriptorProto* message); - bool ParseServiceStatement(ServiceDescriptorProto* message); + bool ParseMessageStatement(DescriptorProto* message, + const LocationRecorder& message_location, + const FileDescriptorProto* containing_file); + bool ParseEnumStatement(EnumDescriptorProto* message, + const LocationRecorder& enum_location, + const FileDescriptorProto* containing_file); + bool ParseServiceStatement(ServiceDescriptorProto* message, + const LocationRecorder& service_location, + const FileDescriptorProto* containing_file); // Parse a field of a message. If the field is a group, its type will be // added to "messages". + // + // parent_location and location_field_number_for_nested_type are needed when + // parsing groups -- we need to generate a nested message type within the + // parent and record its location accordingly. Since the parent could be + // either a FileDescriptorProto or a DescriptorProto, we must pass in the + // correct field number to use. bool ParseMessageField(FieldDescriptorProto* field, - RepeatedPtrField* messages); + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file); + + // Like ParseMessageField() but expects the label has already been filled in + // by the caller. + bool ParseMessageFieldNoLabel(FieldDescriptorProto* field, + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file); // Parse an "extensions" declaration. - bool ParseExtensions(DescriptorProto* message); + bool ParseExtensions(DescriptorProto* message, + const LocationRecorder& extensions_location, + const FileDescriptorProto* containing_file); - // Parse an "extend" declaration. + // Parse an "extend" declaration. (See also comments for + // ParseMessageField().) bool ParseExtend(RepeatedPtrField* extensions, - RepeatedPtrField* messages); + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& extend_location, + const FileDescriptorProto* containing_file); + + // Parse a "oneof" declaration. The caller is responsible for setting + // oneof_decl->label() since it will have had to parse the label before it + // knew it was parsing a oneof. + bool ParseOneof(OneofDescriptorProto* oneof_decl, + DescriptorProto* containing_type, + int oneof_index, + const LocationRecorder& oneof_location, + const LocationRecorder& containing_type_location, + const FileDescriptorProto* containing_file); // Parse a single enum value within an enum block. - bool ParseEnumConstant(EnumValueDescriptorProto* enum_value); + bool ParseEnumConstant(EnumValueDescriptorProto* enum_value, + const LocationRecorder& enum_value_location, + const FileDescriptorProto* containing_file); // Parse enum constant options, i.e. the list in square brackets at the end // of the enum constant value definition. - bool ParseEnumConstantOptions(EnumValueDescriptorProto* value); + bool ParseEnumConstantOptions(EnumValueDescriptorProto* value, + const LocationRecorder& enum_value_location, + const FileDescriptorProto* containing_file); // Parse a single method within a service definition. - bool ParseServiceMethod(MethodDescriptorProto* method); + bool ParseServiceMethod(MethodDescriptorProto* method, + const LocationRecorder& method_location, + const FileDescriptorProto* containing_file); + + + // Parse options of a single method or stream. + bool ParseOptions(const LocationRecorder& parent_location, + const FileDescriptorProto* containing_file, + const int optionsFieldNumber, + Message* mutable_options); // Parse "required", "optional", or "repeated" and fill in "label" // with the value. - bool ParseLabel(FieldDescriptorProto::Label* label); + bool ParseLabel(FieldDescriptorProto::Label* label, + const FileDescriptorProto* containing_file); // Parse a type name and fill in "type" (if it is a primitive) or // "type_name" (if it is not) with the type parsed. @@ -269,39 +417,75 @@ class LIBPROTOBUF_EXPORT Parser { // Parses field options, i.e. the stuff in square brackets at the end // of a field definition. Also parses default value. - bool ParseFieldOptions(FieldDescriptorProto* field); + bool ParseFieldOptions(FieldDescriptorProto* field, + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file); // Parse the "default" option. This needs special handling because its // type is the field's type. - bool ParseDefaultAssignment(FieldDescriptorProto* field); + bool ParseDefaultAssignment(FieldDescriptorProto* field, + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file); + + enum OptionStyle { + OPTION_ASSIGNMENT, // just "name = value" + OPTION_STATEMENT // "option name = value;" + }; // Parse a single option name/value pair, e.g. "ctype = CORD". The name // identifies a field of the given Message, and the value of that field // is set to the parsed value. - bool ParseOptionAssignment(Message* options); + bool ParseOption(Message* options, + const LocationRecorder& options_location, + const FileDescriptorProto* containing_file, + OptionStyle style); // Parses a single part of a multipart option name. A multipart name consists // of names separated by dots. Each name is either an identifier or a series // of identifiers separated by dots and enclosed in parentheses. E.g., // "foo.(bar.baz).qux". - bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option); + bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option, + const LocationRecorder& part_location, + const FileDescriptorProto* containing_file); + + // Parses a string surrounded by balanced braces. Strips off the outer + // braces and stores the enclosed string in *value. + // E.g., + // { foo } *value gets 'foo' + // { foo { bar: box } } *value gets 'foo { bar: box }' + // {} *value gets '' + // + // REQUIRES: LookingAt("{") + // When finished successfully, we are looking at the first token past + // the ending brace. + bool ParseUninterpretedBlock(string* value); // ================================================================= io::Tokenizer* input_; io::ErrorCollector* error_collector_; - SourceLocationTable* source_location_table_; + SourceCodeInfo* source_code_info_; + SourceLocationTable* source_location_table_; // legacy bool had_errors_; bool require_syntax_identifier_; bool stop_after_syntax_identifier_; string syntax_identifier_; + // Leading doc comments for the next declaration. These are not complete + // yet; use ConsumeEndOfDeclaration() to get the complete comments. + string upcoming_doc_comments_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser); }; // A table mapping (descriptor, ErrorLocation) pairs -- as reported by // DescriptorPool when validating descriptors -- to line and column numbers // within the original source code. +// +// This is semi-obsolete: FileDescriptorProto.source_code_info now contains +// far more complete information about source locations. However, as of this +// writing you still need to use SourceLocationTable when integrating with +// DescriptorPool. class LIBPROTOBUF_EXPORT SourceLocationTable { public: SourceLocationTable(); diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index e2262b8..847370a 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -32,8 +32,10 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include #include #include +#include #include @@ -43,8 +45,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -118,6 +122,9 @@ class ParserTest : public testing::Test { EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); ASSERT_EQ("", error_collector_.text_); + // We don't cover SourceCodeInfo in these tests. + actual.clear_source_code_info(); + // Parse the ASCII representation in order to canonicalize it. We could // just compare directly to actual.DebugString(), but that would require // that the caller precisely match the formatting that DebugString() @@ -430,6 +437,69 @@ TEST_F(ParseMessageTest, FieldOptions) { "}"); } +TEST_F(ParseMessageTest, Oneof) { + ExpectParsesTo( + "message TestMessage {\n" + " oneof foo {\n" + " int32 a = 1;\n" + " string b = 2;\n" + " TestMessage c = 3;\n" + " group D = 4 { optional int32 i = 5; }\n" + " }\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " + " oneof_index:0 }" + " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 " + " oneof_index:0 }" + " field { name:\"c\" label:LABEL_OPTIONAL type_name:\"TestMessage\" " + " number:3 oneof_index:0 }" + " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_GROUP " + " type_name:\"D\" number:4 oneof_index:0 }" + " oneof_decl {" + " name: \"foo\"" + " }" + " nested_type {" + " name: \"D\"" + " field { name:\"i\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 }" + " }" + "}"); +} + +TEST_F(ParseMessageTest, MultipleOneofs) { + ExpectParsesTo( + "message TestMessage {\n" + " oneof foo {\n" + " int32 a = 1;\n" + " string b = 2;\n" + " }\n" + " oneof bar {\n" + " int32 c = 3;\n" + " string d = 4;\n" + " }\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " + " oneof_index:0 }" + " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 " + " oneof_index:0 }" + " field { name:\"c\" label:LABEL_OPTIONAL type:TYPE_INT32 number:3 " + " oneof_index:1 }" + " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_STRING number:4 " + " oneof_index:1 }" + " oneof_decl {" + " name: \"foo\"" + " }" + " oneof_decl {" + " name: \"bar\"" + " }" + "}"); +} + TEST_F(ParseMessageTest, Group) { ExpectParsesTo( "message TestMessage {\n" @@ -504,6 +574,31 @@ TEST_F(ParseMessageTest, CompoundExtensionRange) { "}"); } +TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) { + // Messages using the message_set_wire_format option can accept larger + // extension numbers, as the numbers are not encoded as int32 field values + // rather than tags. + ExpectParsesTo( + "message TestMessage {\n" + " extensions 4 to max;\n" + " option message_set_wire_format = true;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " extension_range { start:4 end: 0x7fffffff }" + " options {\n" + " uninterpreted_option { \n" + " name {\n" + " name_part: \"message_set_wire_format\"\n" + " is_extension: false\n" + " }\n" + " identifier_value: \"true\"\n" + " }\n" + " }\n" + "}"); +} + TEST_F(ParseMessageTest, Extensions) { ExpectParsesTo( "extend Extendee1 { optional int32 foo = 12; }\n" @@ -544,6 +639,7 @@ TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) { " type_name:\"TestMessage\" extendee: \"Extendee1\" }"); } + // =================================================================== typedef ParserTest ParseEnumTest; @@ -566,6 +662,10 @@ TEST_F(ParseEnumTest, Values) { " FOO = 13;\n" " BAR = -10;\n" " BAZ = 500;\n" + " HEX_MAX = 0x7FFFFFFF;\n" + " HEX_MIN = -0x80000000;\n" + " INT_MAX = 2147483647;\n" + " INT_MIN = -2147483648;\n" "}\n", "enum_type {" @@ -573,6 +673,10 @@ TEST_F(ParseEnumTest, Values) { " value { name:\"FOO\" number:13 }" " value { name:\"BAR\" number:-10 }" " value { name:\"BAZ\" number:500 }" + " value { name:\"HEX_MAX\" number:2147483647 }" + " value { name:\"HEX_MIN\" number:-2147483648 }" + " value { name:\"INT_MAX\" number:2147483647 }" + " value { name:\"INT_MIN\" number:-2147483648 }" "}"); } @@ -626,7 +730,7 @@ TEST_F(ParseServiceTest, SimpleService) { "}"); } -TEST_F(ParseServiceTest, Methods) { +TEST_F(ParseServiceTest, MethodsAndStreams) { ExpectParsesTo( "service TestService {\n" " rpc Foo(In1) returns (Out1);\n" @@ -642,6 +746,8 @@ TEST_F(ParseServiceTest, Methods) { "}"); } + + // =================================================================== // imports and packages @@ -663,6 +769,20 @@ TEST_F(ParseMiscTest, ParseMultipleImports) { "dependency: \"baz.proto\""); } +TEST_F(ParseMiscTest, ParsePublicImports) { + ExpectParsesTo( + "import \"foo.proto\";\n" + "import public \"bar.proto\";\n" + "import \"baz.proto\";\n" + "import public \"qux.proto\";\n", + "dependency: \"foo.proto\"" + "dependency: \"bar.proto\"" + "dependency: \"baz.proto\"" + "dependency: \"qux.proto\"" + "public_dependency: 1 " + "public_dependency: 3 "); +} + TEST_F(ParseMiscTest, ParsePackage) { ExpectParsesTo( "package foo.bar.baz;\n", @@ -817,7 +937,7 @@ TEST_F(ParseErrorTest, DefaultValueTypeMismatch) { "message TestMessage {\n" " optional uint32 foo = 1 [default=true];\n" "}\n", - "1:35: Expected integer.\n"); + "1:35: Expected integer for field default value.\n"); } TEST_F(ParseErrorTest, DefaultValueNotBoolean) { @@ -833,7 +953,7 @@ TEST_F(ParseErrorTest, DefaultValueNotString) { "message TestMessage {\n" " optional string foo = 1 [default=1];\n" "}\n", - "1:35: Expected string.\n"); + "1:35: Expected string for field default value.\n"); } TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) { @@ -862,12 +982,26 @@ TEST_F(ParseErrorTest, DefaultValueTooLarge) { "6:36: Integer out of range.\n"); } +TEST_F(ParseErrorTest, EnumValueOutOfRange) { + ExpectHasErrors( + "enum TestEnum {\n" + " HEX_TOO_BIG = 0x80000000;\n" + " HEX_TOO_SMALL = -0x80000001;\n" + " INT_TOO_BIG = 2147483648;\n" + " INT_TOO_SMALL = -2147483649;\n" + "}\n", + "1:19: Integer out of range.\n" + "2:19: Integer out of range.\n" + "3:19: Integer out of range.\n" + "4:19: Integer out of range.\n"); +} + TEST_F(ParseErrorTest, DefaultValueMissing) { ExpectHasErrors( "message TestMessage {\n" " optional uint32 foo = 1 [default=];\n" "}\n", - "1:35: Expected integer.\n"); + "1:35: Expected integer for field default value.\n"); } TEST_F(ParseErrorTest, DefaultValueForGroup) { @@ -886,6 +1020,27 @@ TEST_F(ParseErrorTest, DuplicateDefaultValue) { "1:37: Already set option \"default\".\n"); } +TEST_F(ParseErrorTest, MissingOneofName) { + ExpectHasErrors( + "message TestMessage {\n" + " oneof {\n" + " int32 bar = 1;\n" + " }\n" + "}\n", + "1:8: Expected oneof name.\n"); +} + +TEST_F(ParseErrorTest, LabelInOneof) { + ExpectHasErrors( + "message TestMessage {\n" + " oneof foo {\n" + " optional int32 bar = 1;\n" + " }\n" + "}\n", + "2:4: Fields in oneofs must not have labels (required / optional " + "/ repeated).\n"); +} + TEST_F(ParseErrorTest, GroupNotCapitalized) { ExpectHasErrors( "message TestMessage {\n" @@ -930,6 +1085,12 @@ TEST_F(ParseErrorTest, MultipleParseErrors) { "3:25: Expected \";\".\n"); } +TEST_F(ParseErrorTest, EofInAggregateValue) { + ExpectHasErrors( + "option (fileopt) = { i:100\n", + "1:0: Unexpected end of stream while parsing aggregate value.\n"); +} + // ------------------------------------------------------------------- // Enum errors @@ -965,6 +1126,7 @@ TEST_F(ParseErrorTest, ServiceMethodPrimitiveParams) { "1:26: Expected message type.\n"); } + TEST_F(ParseErrorTest, EofInMethodOptions) { ExpectHasErrors( "service TestService {\n" @@ -973,6 +1135,7 @@ TEST_F(ParseErrorTest, EofInMethodOptions) { "1:29: Reached end of input in service definition (missing '}').\n"); } + TEST_F(ParseErrorTest, PrimitiveMethodInput) { ExpectHasErrors( "service TestService {\n" @@ -981,6 +1144,7 @@ TEST_F(ParseErrorTest, PrimitiveMethodInput) { "1:10: Expected message type.\n"); } + TEST_F(ParseErrorTest, MethodOptionTypeError) { // This used to cause an infinite loop. ExpectHasErrors( @@ -991,6 +1155,7 @@ TEST_F(ParseErrorTest, MethodOptionTypeError) { "2:45: Expected \"=\".\n"); } + // ------------------------------------------------------------------- // Import and package errors @@ -1146,6 +1311,7 @@ TEST_F(ParserValidationErrorTest, MethodNameError) { "3:6: \"Bar\" is already defined in \"Foo\".\n"); } + TEST_F(ParserValidationErrorTest, MethodInputTypeError) { ExpectHasValidationErrors( "message Baz {}\n" @@ -1155,6 +1321,7 @@ TEST_F(ParserValidationErrorTest, MethodInputTypeError) { "2:10: \"Qux\" is not defined.\n"); } + TEST_F(ParserValidationErrorTest, MethodOutputTypeError) { ExpectHasValidationErrors( "message Baz {}\n" @@ -1164,17 +1331,94 @@ TEST_F(ParserValidationErrorTest, MethodOutputTypeError) { "2:23: \"Qux\" is not defined.\n"); } + +TEST_F(ParserValidationErrorTest, ResovledUndefinedError) { + // Create another file which defines symbol ".base.bar". + FileDescriptorProto other_file; + other_file.set_name("base.proto"); + other_file.set_package("base"); + other_file.add_message_type()->set_name("bar"); + EXPECT_TRUE(pool_.BuildFile(other_file) != NULL); + + // Define "foo.base" and try "base.bar". + // "base.bar" is resolved to "foo.base.bar" which is not defined. + ExpectHasValidationErrors( + "package foo.base;\n" + "import \"base.proto\";\n" + "message qux {\n" + " optional base.bar baz = 1;\n" + " optional .base.bar quz = 2;\n" + "}\n", + "3:11: \"base.bar\" is resolved to \"foo.base.bar\"," + " which is not defined. The innermost scope is searched first " + "in name resolution. Consider using a leading '.'(i.e., \".base.bar\")" + " to start from the outermost scope.\n"); +} + +TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) { + // Build descriptor message in test pool + FileDescriptorProto descriptor_proto; + DescriptorProto::descriptor()->file()->CopyTo(&descriptor_proto); + ASSERT_TRUE(pool_.BuildFile(descriptor_proto) != NULL); + + // base2.proto: + // package baz + // import google/protobuf/descriptor.proto + // message Bar { optional int32 foo = 1; } + // extend FileOptions { optional Bar bar = 7672757; } + FileDescriptorProto other_file; + other_file.set_name("base2.proto"); + other_file.set_package("baz"); + other_file.add_dependency(); + other_file.set_dependency(0, descriptor_proto.name()); + + DescriptorProto* message(other_file.add_message_type()); + message->set_name("Bar"); + FieldDescriptorProto* field(message->add_field()); + field->set_name("foo"); + field->set_number(1); + field->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL); + field->set_type(FieldDescriptorProto_Type_TYPE_INT32); + + FieldDescriptorProto* extension(other_file.add_extension()); + extension->set_name("bar"); + extension->set_number(7672757); + extension->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL); + extension->set_type(FieldDescriptorProto_Type_TYPE_MESSAGE); + extension->set_type_name("Bar"); + extension->set_extendee("google.protobuf.FileOptions"); + + EXPECT_TRUE(pool_.BuildFile(other_file) != NULL); + + // qux.proto: + // package qux.baz + // option (baz.bar).foo = 1; + // + // Although "baz.bar" is already defined, the lookup code will try + // "qux.baz.bar", since it's the match from the innermost scope, + // which will cause a symbol not defined error. + ExpectHasValidationErrors( + "package qux.baz;\n" + "import \"base2.proto\";\n" + "option (baz.bar).foo = 1;\n", + "2:7: Option \"(baz.bar)\" is resolved to \"(qux.baz.bar)\"," + " which is not defined. The innermost scope is searched first " + "in name resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\")" + " to start from the outermost scope.\n"); +} + // =================================================================== // Test that the output from FileDescriptor::DebugString() (and all other // descriptor types) is parseable, and results in the same Descriptor -// definitions again afoter parsing (not, however, that the order of messages +// definitions again afoter parsing (note, however, that the order of messages // cannot be guaranteed to be the same) typedef ParserTest ParseDecriptorDebugTest; class CompareDescriptorNames { public: - bool operator()(const DescriptorProto* left, const DescriptorProto* right) { + bool operator()(const DescriptorProto* left, + const DescriptorProto* right) const { return left->name() < right->name(); } }; @@ -1218,13 +1462,19 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) { FileDescriptorProto parsed; parser_->Parse(input_.get(), &parsed); EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); - ASSERT_EQ("", error_collector_.text_); + ASSERT_EQ("", error_collector_.text_) + << "Failed to parse:\n" << debug_string; // We now have a FileDescriptorProto, but to compare with the expected we // need to link to a FileDecriptor, then output back to a proto. We'll // also need to give it the same name as the original. parsed.set_name("google/protobuf/unittest.proto"); // We need the imported dependency before we can build our parsed proto + const FileDescriptor* public_import = + protobuf_unittest_import::PublicImportMessage::descriptor()->file(); + FileDescriptorProto public_import_proto; + public_import->CopyTo(&public_import_proto); + ASSERT_TRUE(pool_.BuildFile(public_import_proto) != NULL); const FileDescriptor* import = protobuf_unittest_import::ImportMessage::descriptor()->file(); FileDescriptorProto import_proto; @@ -1232,6 +1482,8 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) { ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL); const FileDescriptor* actual = pool_.BuildFile(parsed); parsed.Clear(); + ASSERT_TRUE(actual != NULL) + << "Failed to validate:\n" << debug_string; actual->CopyTo(&parsed); ASSERT_TRUE(actual != NULL); @@ -1247,6 +1499,1110 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) { EXPECT_EQ(expected.DebugString(), parsed.DebugString()); } +TEST_F(ParseDecriptorDebugTest, TestCustomOptions) { + const FileDescriptor* original_file = + protobuf_unittest::AggregateMessage::descriptor()->file(); + FileDescriptorProto expected; + original_file->CopyTo(&expected); + + string debug_string = original_file->DebugString(); + + // Parse the debug string + SetupParser(debug_string.c_str()); + FileDescriptorProto parsed; + parser_->Parse(input_.get(), &parsed); + EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); + ASSERT_EQ("", error_collector_.text_); + + // We now have a FileDescriptorProto, but to compare with the expected we + // need to link to a FileDecriptor, then output back to a proto. We'll + // also need to give it the same name as the original. + parsed.set_name(original_file->name()); + + // unittest_custom_options.proto depends on descriptor.proto. + const FileDescriptor* import = FileDescriptorProto::descriptor()->file(); + FileDescriptorProto import_proto; + import->CopyTo(&import_proto); + ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL); + const FileDescriptor* actual = pool_.BuildFile(parsed); + ASSERT_TRUE(actual != NULL); + parsed.Clear(); + actual->CopyTo(&parsed); + + // The messages might be in different orders, making them hard to compare. + // So, sort the messages in the descriptor protos (including nested messages, + // recursively). + SortMessages(&expected); + SortMessages(&parsed); + + EXPECT_EQ(expected.DebugString(), parsed.DebugString()); +} + +// =================================================================== +// SourceCodeInfo tests. + +// Follows a path -- as defined by SourceCodeInfo.Location.path -- from a +// message to a particular sub-field. +// * If the target is itself a message, sets *output_message to point at it, +// *output_field to NULL, and *output_index to -1. +// * Otherwise, if the target is an element of a repeated field, sets +// *output_message to the containing message, *output_field to the descriptor +// of the field, and *output_index to the index of the element. +// * Otherwise, the target is a field (possibly a repeated field, but not any +// one element). Sets *output_message to the containing message, +// *output_field to the descriptor of the field, and *output_index to -1. +// Returns true if the path was valid, false otherwise. A gTest failure is +// recorded before returning false. +bool FollowPath(const Message& root, + const int* path_begin, const int* path_end, + const Message** output_message, + const FieldDescriptor** output_field, + int* output_index) { + if (path_begin == path_end) { + // Path refers to this whole message. + *output_message = &root; + *output_field = NULL; + *output_index = -1; + return true; + } + + const Descriptor* descriptor = root.GetDescriptor(); + const Reflection* reflection = root.GetReflection(); + + const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin); + + if (field == NULL) { + ADD_FAILURE() << descriptor->name() << " has no field number: " + << *path_begin; + return false; + } + + ++path_begin; + + if (field->is_repeated()) { + if (path_begin == path_end) { + // Path refers to the whole repeated field. + *output_message = &root; + *output_field = field; + *output_index = -1; + return true; + } + + int index = *path_begin++; + int size = reflection->FieldSize(root, field); + + if (index >= size) { + ADD_FAILURE() << descriptor->name() << "." << field->name() + << " has size " << size << ", but path contained index: " + << index; + return false; + } + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // Descend into child message. + const Message& child = reflection->GetRepeatedMessage(root, field, index); + return FollowPath(child, path_begin, path_end, + output_message, output_field, output_index); + } else if (path_begin == path_end) { + // Path refers to this element. + *output_message = &root; + *output_field = field; + *output_index = index; + return true; + } else { + ADD_FAILURE() << descriptor->name() << "." << field->name() + << " is not a message; cannot descend into it."; + return false; + } + } else { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + const Message& child = reflection->GetMessage(root, field); + return FollowPath(child, path_begin, path_end, + output_message, output_field, output_index); + } else if (path_begin == path_end) { + // Path refers to this field. + *output_message = &root; + *output_field = field; + *output_index = -1; + return true; + } else { + ADD_FAILURE() << descriptor->name() << "." << field->name() + << " is not a message; cannot descend into it."; + return false; + } + } +} + +// Check if two spans are equal. +bool CompareSpans(const RepeatedField& span1, + const RepeatedField& span2) { + if (span1.size() != span2.size()) return false; + for (int i = 0; i < span1.size(); i++) { + if (span1.Get(i) != span2.Get(i)) return false; + } + return true; +} + +// Test fixture for source info tests, which check that source locations are +// recorded correctly in FileDescriptorProto.source_code_info.location. +class SourceInfoTest : public ParserTest { + protected: + // The parsed file (initialized by Parse()). + FileDescriptorProto file_; + + // Parse the given text as a .proto file and populate the spans_ map with + // all the source location spans in its SourceCodeInfo table. + bool Parse(const char* text) { + ExtractMarkers(text); + SetupParser(text_without_markers_.c_str()); + if (!parser_->Parse(input_.get(), &file_)) { + return false; + } + + const SourceCodeInfo& source_info = file_.source_code_info(); + for (int i = 0; i < source_info.location_size(); i++) { + const SourceCodeInfo::Location& location = source_info.location(i); + const Message* descriptor_proto = NULL; + const FieldDescriptor* field = NULL; + int index = 0; + if (!FollowPath(file_, location.path().begin(), location.path().end(), + &descriptor_proto, &field, &index)) { + return false; + } + + spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index), + &location)); + } + + return true; + } + + virtual void TearDown() { + EXPECT_TRUE(spans_.empty()) + << "Forgot to call HasSpan() for:\n" + << spans_.begin()->second->DebugString(); + } + + // ----------------------------------------------------------------- + // HasSpan() checks that the span of source code delimited by the given + // tags (comments) correspond via the SourceCodeInfo table to the given + // part of the FileDescriptorProto. (If unclear, look at the actual tests; + // it should quickly become obvious.) + + bool HasSpan(char start_marker, char end_marker, + const Message& descriptor_proto) { + return HasSpanWithComment( + start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL); + } + + bool HasSpanWithComment(char start_marker, char end_marker, + const Message& descriptor_proto, + const char* expected_leading_comments, + const char* expected_trailing_comments) { + return HasSpanWithComment( + start_marker, end_marker, descriptor_proto, NULL, -1, + expected_leading_comments, expected_trailing_comments); + } + + bool HasSpan(char start_marker, char end_marker, + const Message& descriptor_proto, const string& field_name) { + return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1); + } + + bool HasSpan(char start_marker, char end_marker, + const Message& descriptor_proto, const string& field_name, + int index) { + return HasSpan(start_marker, end_marker, descriptor_proto, + field_name, index, NULL, NULL); + } + + bool HasSpan(char start_marker, char end_marker, + const Message& descriptor_proto, + const string& field_name, int index, + const char* expected_leading_comments, + const char* expected_trailing_comments) { + const FieldDescriptor* field = + descriptor_proto.GetDescriptor()->FindFieldByName(field_name); + if (field == NULL) { + ADD_FAILURE() << descriptor_proto.GetDescriptor()->name() + << " has no such field: " << field_name; + return false; + } + + return HasSpanWithComment( + start_marker, end_marker, descriptor_proto, field, index, + expected_leading_comments, expected_trailing_comments); + } + + bool HasSpan(const Message& descriptor_proto) { + return HasSpanWithComment( + '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL); + } + + bool HasSpan(const Message& descriptor_proto, const string& field_name) { + return HasSpan('\0', '\0', descriptor_proto, field_name, -1); + } + + bool HasSpan(const Message& descriptor_proto, const string& field_name, + int index) { + return HasSpan('\0', '\0', descriptor_proto, field_name, index); + } + + bool HasSpanWithComment(char start_marker, char end_marker, + const Message& descriptor_proto, + const FieldDescriptor* field, int index, + const char* expected_leading_comments, + const char* expected_trailing_comments) { + pair range = + spans_.equal_range(SpanKey(descriptor_proto, field, index)); + + if (start_marker == '\0') { + if (range.first == range.second) { + return false; + } else { + spans_.erase(range.first); + return true; + } + } else { + pair start_pos = FindOrDie(markers_, start_marker); + pair end_pos = FindOrDie(markers_, end_marker); + + RepeatedField expected_span; + expected_span.Add(start_pos.first); + expected_span.Add(start_pos.second); + if (end_pos.first != start_pos.first) { + expected_span.Add(end_pos.first); + } + expected_span.Add(end_pos.second); + + for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) { + if (CompareSpans(expected_span, iter->second->span())) { + if (expected_leading_comments == NULL) { + EXPECT_FALSE(iter->second->has_leading_comments()); + } else { + EXPECT_TRUE(iter->second->has_leading_comments()); + EXPECT_EQ(expected_leading_comments, + iter->second->leading_comments()); + } + if (expected_trailing_comments == NULL) { + EXPECT_FALSE(iter->second->has_trailing_comments()); + } else { + EXPECT_TRUE(iter->second->has_trailing_comments()); + EXPECT_EQ(expected_trailing_comments, + iter->second->trailing_comments()); + } + + spans_.erase(iter); + return true; + } + } + + return false; + } + } + + private: + struct SpanKey { + const Message* descriptor_proto; + const FieldDescriptor* field; + int index; + + inline SpanKey() {} + inline SpanKey(const Message& descriptor_proto_param, + const FieldDescriptor* field_param, + int index_param) + : descriptor_proto(&descriptor_proto_param), field(field_param), + index(index_param) {} + + inline bool operator<(const SpanKey& other) const { + if (descriptor_proto < other.descriptor_proto) return true; + if (descriptor_proto > other.descriptor_proto) return false; + if (field < other.field) return true; + if (field > other.field) return false; + return index < other.index; + } + }; + + typedef multimap SpanMap; + SpanMap spans_; + map > markers_; + string text_without_markers_; + + void ExtractMarkers(const char* text) { + markers_.clear(); + text_without_markers_.clear(); + int line = 0; + int column = 0; + while (*text != '\0') { + if (*text == '$') { + ++text; + GOOGLE_CHECK_NE('\0', *text); + if (*text == '$') { + text_without_markers_ += '$'; + ++column; + } else { + markers_[*text] = make_pair(line, column); + ++text; + GOOGLE_CHECK_EQ('$', *text); + } + } else if (*text == '\n') { + ++line; + column = 0; + text_without_markers_ += *text; + } else { + text_without_markers_ += *text; + ++column; + } + ++text; + } + } +}; + +TEST_F(SourceInfoTest, BasicFileDecls) { + EXPECT_TRUE(Parse( + "$a$syntax = \"proto2\";\n" + "package $b$foo.bar$c$;\n" + "import $d$\"baz.proto\"$e$;\n" + "import $f$\"qux.proto\"$g$;$h$\n" + "\n" + "// comment ignored\n")); + + EXPECT_TRUE(HasSpan('a', 'h', file_)); + EXPECT_TRUE(HasSpan('b', 'c', file_, "package")); + EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0)); + EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1)); +} + +TEST_F(SourceInfoTest, Messages) { + EXPECT_TRUE(Parse( + "$a$message $b$Foo$c$ {}$d$\n" + "$e$message $f$Bar$g$ {}$h$\n")); + + EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0))); + EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan('e', 'h', file_.message_type(1))); + EXPECT_TRUE(HasSpan('f', 'g', file_.message_type(1), "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); +} + +TEST_F(SourceInfoTest, Fields) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " $a$optional$b$ $c$int32$d$ $e$bar$f$ = $g$1$h$;$i$\n" + " $j$repeated$k$ $l$X.Y$m$ $n$baz$o$ = $p$2$q$;$r$\n" + "}\n")); + + const FieldDescriptorProto& field1 = file_.message_type(0).field(0); + const FieldDescriptorProto& field2 = file_.message_type(0).field(1); + + EXPECT_TRUE(HasSpan('a', 'i', field1)); + EXPECT_TRUE(HasSpan('a', 'b', field1, "label")); + EXPECT_TRUE(HasSpan('c', 'd', field1, "type")); + EXPECT_TRUE(HasSpan('e', 'f', field1, "name")); + EXPECT_TRUE(HasSpan('g', 'h', field1, "number")); + + EXPECT_TRUE(HasSpan('j', 'r', field2)); + EXPECT_TRUE(HasSpan('j', 'k', field2, "label")); + EXPECT_TRUE(HasSpan('l', 'm', field2, "type_name")); + EXPECT_TRUE(HasSpan('n', 'o', field2, "name")); + EXPECT_TRUE(HasSpan('p', 'q', field2, "number")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + +TEST_F(SourceInfoTest, Extensions) { + EXPECT_TRUE(Parse( + "$a$extend $b$Foo$c$ {\n" + " $d$optional$e$ int32 bar = 1;$f$\n" + " $g$repeated$h$ X.Y baz = 2;$i$\n" + "}$j$\n" + "$k$extend $l$Bar$m$ {\n" + " $n$optional int32 qux = 1;$o$\n" + "}$p$\n")); + + const FieldDescriptorProto& field1 = file_.extension(0); + const FieldDescriptorProto& field2 = file_.extension(1); + const FieldDescriptorProto& field3 = file_.extension(2); + + EXPECT_TRUE(HasSpan('a', 'j', file_, "extension")); + EXPECT_TRUE(HasSpan('k', 'p', file_, "extension")); + + EXPECT_TRUE(HasSpan('d', 'f', field1)); + EXPECT_TRUE(HasSpan('d', 'e', field1, "label")); + EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee")); + + EXPECT_TRUE(HasSpan('g', 'i', field2)); + EXPECT_TRUE(HasSpan('g', 'h', field2, "label")); + EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee")); + + EXPECT_TRUE(HasSpan('n', 'o', field3)); + EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(field1, "type")); + EXPECT_TRUE(HasSpan(field1, "name")); + EXPECT_TRUE(HasSpan(field1, "number")); + EXPECT_TRUE(HasSpan(field2, "type_name")); + EXPECT_TRUE(HasSpan(field2, "name")); + EXPECT_TRUE(HasSpan(field2, "number")); + EXPECT_TRUE(HasSpan(field3, "label")); + EXPECT_TRUE(HasSpan(field3, "type")); + EXPECT_TRUE(HasSpan(field3, "name")); + EXPECT_TRUE(HasSpan(field3, "number")); +} + +TEST_F(SourceInfoTest, NestedExtensions) { + EXPECT_TRUE(Parse( + "message Message {\n" + " $a$extend $b$Foo$c$ {\n" + " $d$optional$e$ int32 bar = 1;$f$\n" + " $g$repeated$h$ X.Y baz = 2;$i$\n" + " }$j$\n" + " $k$extend $l$Bar$m$ {\n" + " $n$optional int32 qux = 1;$o$\n" + " }$p$\n" + "}\n")); + + const FieldDescriptorProto& field1 = file_.message_type(0).extension(0); + const FieldDescriptorProto& field2 = file_.message_type(0).extension(1); + const FieldDescriptorProto& field3 = file_.message_type(0).extension(2); + + EXPECT_TRUE(HasSpan('a', 'j', file_.message_type(0), "extension")); + EXPECT_TRUE(HasSpan('k', 'p', file_.message_type(0), "extension")); + + EXPECT_TRUE(HasSpan('d', 'f', field1)); + EXPECT_TRUE(HasSpan('d', 'e', field1, "label")); + EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee")); + + EXPECT_TRUE(HasSpan('g', 'i', field2)); + EXPECT_TRUE(HasSpan('g', 'h', field2, "label")); + EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee")); + + EXPECT_TRUE(HasSpan('n', 'o', field3)); + EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan(field1, "type")); + EXPECT_TRUE(HasSpan(field1, "name")); + EXPECT_TRUE(HasSpan(field1, "number")); + EXPECT_TRUE(HasSpan(field2, "type_name")); + EXPECT_TRUE(HasSpan(field2, "name")); + EXPECT_TRUE(HasSpan(field2, "number")); + EXPECT_TRUE(HasSpan(field3, "label")); + EXPECT_TRUE(HasSpan(field3, "type")); + EXPECT_TRUE(HasSpan(field3, "name")); + EXPECT_TRUE(HasSpan(field3, "number")); +} + +TEST_F(SourceInfoTest, ExtensionRanges) { + EXPECT_TRUE(Parse( + "message Message {\n" + " $a$extensions $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n" + " $i$extensions $j$8$k$ to $l$max$m$;$n$\n" + "}\n")); + + const DescriptorProto::ExtensionRange& range1 = + file_.message_type(0).extension_range(0); + const DescriptorProto::ExtensionRange& range2 = + file_.message_type(0).extension_range(1); + const DescriptorProto::ExtensionRange& range3 = + file_.message_type(0).extension_range(2); + + EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "extension_range")); + EXPECT_TRUE(HasSpan('i', 'n', file_.message_type(0), "extension_range")); + + EXPECT_TRUE(HasSpan('b', 'e', range1)); + EXPECT_TRUE(HasSpan('b', 'c', range1, "start")); + EXPECT_TRUE(HasSpan('d', 'e', range1, "end")); + + EXPECT_TRUE(HasSpan('f', 'g', range2)); + EXPECT_TRUE(HasSpan('f', 'g', range2, "start")); + EXPECT_TRUE(HasSpan('f', 'g', range2, "end")); + + EXPECT_TRUE(HasSpan('j', 'm', range3)); + EXPECT_TRUE(HasSpan('j', 'k', range3, "start")); + EXPECT_TRUE(HasSpan('l', 'm', range3, "end")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + +TEST_F(SourceInfoTest, Oneofs) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " $a$oneof $c$foo$d$ {\n" + " $e$int32$f$ $g$a$h$ = $i$1$j$;$k$\n" + " }$r$\n" + "}\n")); + + const OneofDescriptorProto& oneof_decl = file_.message_type(0).oneof_decl(0); + const FieldDescriptorProto& field = file_.message_type(0).field(0); + + EXPECT_TRUE(HasSpan('a', 'r', oneof_decl)); + EXPECT_TRUE(HasSpan('c', 'd', oneof_decl, "name")); + + EXPECT_TRUE(HasSpan('e', 'k', field)); + EXPECT_TRUE(HasSpan('e', 'f', field, "type")); + EXPECT_TRUE(HasSpan('g', 'h', field, "name")); + EXPECT_TRUE(HasSpan('i', 'j', field, "number")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + +TEST_F(SourceInfoTest, NestedMessages) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " $a$message $b$Bar$c$ {\n" + " $d$message $e$Baz$f$ {}$g$\n" + " }$h$\n" + " $i$message $j$Qux$k$ {}$l$\n" + "}\n")); + + const DescriptorProto& bar = file_.message_type(0).nested_type(0); + const DescriptorProto& baz = bar.nested_type(0); + const DescriptorProto& qux = file_.message_type(0).nested_type(1); + + EXPECT_TRUE(HasSpan('a', 'h', bar)); + EXPECT_TRUE(HasSpan('b', 'c', bar, "name")); + EXPECT_TRUE(HasSpan('d', 'g', baz)); + EXPECT_TRUE(HasSpan('e', 'f', baz, "name")); + EXPECT_TRUE(HasSpan('i', 'l', qux)); + EXPECT_TRUE(HasSpan('j', 'k', qux, "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + +TEST_F(SourceInfoTest, Groups) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " message Bar {}\n" + " $a$optional$b$ $c$group$d$ $e$Baz$f$ = $g$1$h$ {\n" + " $i$message Qux {}$j$\n" + " }$k$\n" + "}\n")); + + const DescriptorProto& bar = file_.message_type(0).nested_type(0); + const DescriptorProto& baz = file_.message_type(0).nested_type(1); + const DescriptorProto& qux = baz.nested_type(0); + const FieldDescriptorProto& field = file_.message_type(0).field(0); + + EXPECT_TRUE(HasSpan('a', 'k', field)); + EXPECT_TRUE(HasSpan('a', 'b', field, "label")); + EXPECT_TRUE(HasSpan('c', 'd', field, "type")); + EXPECT_TRUE(HasSpan('e', 'f', field, "name")); + EXPECT_TRUE(HasSpan('e', 'f', field, "type_name")); + EXPECT_TRUE(HasSpan('g', 'h', field, "number")); + + EXPECT_TRUE(HasSpan('a', 'k', baz)); + EXPECT_TRUE(HasSpan('e', 'f', baz, "name")); + EXPECT_TRUE(HasSpan('i', 'j', qux)); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan(bar)); + EXPECT_TRUE(HasSpan(bar, "name")); + EXPECT_TRUE(HasSpan(qux, "name")); +} + +TEST_F(SourceInfoTest, Enums) { + EXPECT_TRUE(Parse( + "$a$enum $b$Foo$c$ {}$d$\n" + "$e$enum $f$Bar$g$ {}$h$\n")); + + EXPECT_TRUE(HasSpan('a', 'd', file_.enum_type(0))); + EXPECT_TRUE(HasSpan('b', 'c', file_.enum_type(0), "name")); + EXPECT_TRUE(HasSpan('e', 'h', file_.enum_type(1))); + EXPECT_TRUE(HasSpan('f', 'g', file_.enum_type(1), "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); +} + +TEST_F(SourceInfoTest, EnumValues) { + EXPECT_TRUE(Parse( + "enum Foo {\n" + " $a$BAR$b$ = $c$1$d$;$e$\n" + " $f$BAZ$g$ = $h$2$i$;$j$\n" + "}")); + + const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0); + const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1); + + EXPECT_TRUE(HasSpan('a', 'e', bar)); + EXPECT_TRUE(HasSpan('a', 'b', bar, "name")); + EXPECT_TRUE(HasSpan('c', 'd', bar, "number")); + EXPECT_TRUE(HasSpan('f', 'j', baz)); + EXPECT_TRUE(HasSpan('f', 'g', baz, "name")); + EXPECT_TRUE(HasSpan('h', 'i', baz, "number")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.enum_type(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); +} + +TEST_F(SourceInfoTest, NestedEnums) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " $a$enum $b$Bar$c$ {}$d$\n" + " $e$enum $f$Baz$g$ {}$h$\n" + "}\n")); + + const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0); + const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1); + + EXPECT_TRUE(HasSpan('a', 'd', bar)); + EXPECT_TRUE(HasSpan('b', 'c', bar, "name")); + EXPECT_TRUE(HasSpan('e', 'h', baz)); + EXPECT_TRUE(HasSpan('f', 'g', baz, "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + +TEST_F(SourceInfoTest, Services) { + EXPECT_TRUE(Parse( + "$a$service $b$Foo$c$ {}$d$\n" + "$e$service $f$Bar$g$ {}$h$\n")); + + EXPECT_TRUE(HasSpan('a', 'd', file_.service(0))); + EXPECT_TRUE(HasSpan('b', 'c', file_.service(0), "name")); + EXPECT_TRUE(HasSpan('e', 'h', file_.service(1))); + EXPECT_TRUE(HasSpan('f', 'g', file_.service(1), "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); +} + +TEST_F(SourceInfoTest, MethodsAndStreams) { + EXPECT_TRUE(Parse( + "service Foo {\n" + " $a$rpc $b$Bar$c$($d$X$e$) returns($f$Y$g$);$h$" + " $i$rpc $j$Baz$k$($l$Z$m$) returns($n$W$o$);$p$" + "}")); + + const MethodDescriptorProto& bar = file_.service(0).method(0); + const MethodDescriptorProto& baz = file_.service(0).method(1); + + EXPECT_TRUE(HasSpan('a', 'h', bar)); + EXPECT_TRUE(HasSpan('b', 'c', bar, "name")); + EXPECT_TRUE(HasSpan('d', 'e', bar, "input_type")); + EXPECT_TRUE(HasSpan('f', 'g', bar, "output_type")); + + EXPECT_TRUE(HasSpan('i', 'p', baz)); + EXPECT_TRUE(HasSpan('j', 'k', baz, "name")); + EXPECT_TRUE(HasSpan('l', 'm', baz, "input_type")); + EXPECT_TRUE(HasSpan('n', 'o', baz, "output_type")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.service(0))); + EXPECT_TRUE(HasSpan(file_.service(0), "name")); +} + + +TEST_F(SourceInfoTest, Options) { + EXPECT_TRUE(Parse( + "$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = " + "$h$123$i$;$j$\n" + "$k$option qux = $l$-123$m$;$n$\n" + "$o$option corge = $p$abc$q$;$r$\n" + "$s$option grault = $t$'blah'$u$;$v$\n" + "$w$option garply = $x${ yadda yadda }$y$;$z$\n" + "$0$option waldo = $1$123.0$2$;$3$\n" + )); + + const UninterpretedOption& option1 = file_.options().uninterpreted_option(0); + const UninterpretedOption& option2 = file_.options().uninterpreted_option(1); + const UninterpretedOption& option3 = file_.options().uninterpreted_option(2); + const UninterpretedOption& option4 = file_.options().uninterpreted_option(3); + const UninterpretedOption& option5 = file_.options().uninterpreted_option(4); + const UninterpretedOption& option6 = file_.options().uninterpreted_option(5); + + EXPECT_TRUE(HasSpan('a', 'j', file_.options())); + EXPECT_TRUE(HasSpan('a', 'j', option1)); + EXPECT_TRUE(HasSpan('b', 'g', option1, "name")); + EXPECT_TRUE(HasSpan('b', 'c', option1.name(0))); + EXPECT_TRUE(HasSpan('b', 'c', option1.name(0), "name_part")); + EXPECT_TRUE(HasSpan('d', 'g', option1.name(1))); + EXPECT_TRUE(HasSpan('e', 'f', option1.name(1), "name_part")); + EXPECT_TRUE(HasSpan('h', 'i', option1, "positive_int_value")); + + EXPECT_TRUE(HasSpan('k', 'n', file_.options())); + EXPECT_TRUE(HasSpan('l', 'm', option2, "negative_int_value")); + + EXPECT_TRUE(HasSpan('o', 'r', file_.options())); + EXPECT_TRUE(HasSpan('p', 'q', option3, "identifier_value")); + + EXPECT_TRUE(HasSpan('s', 'v', file_.options())); + EXPECT_TRUE(HasSpan('t', 'u', option4, "string_value")); + + EXPECT_TRUE(HasSpan('w', 'z', file_.options())); + EXPECT_TRUE(HasSpan('x', 'y', option5, "aggregate_value")); + + EXPECT_TRUE(HasSpan('0', '3', file_.options())); + EXPECT_TRUE(HasSpan('1', '2', option6, "double_value")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(option2)); + EXPECT_TRUE(HasSpan(option3)); + EXPECT_TRUE(HasSpan(option4)); + EXPECT_TRUE(HasSpan(option5)); + EXPECT_TRUE(HasSpan(option6)); + EXPECT_TRUE(HasSpan(option2, "name")); + EXPECT_TRUE(HasSpan(option3, "name")); + EXPECT_TRUE(HasSpan(option4, "name")); + EXPECT_TRUE(HasSpan(option5, "name")); + EXPECT_TRUE(HasSpan(option6, "name")); + EXPECT_TRUE(HasSpan(option2.name(0))); + EXPECT_TRUE(HasSpan(option3.name(0))); + EXPECT_TRUE(HasSpan(option4.name(0))); + EXPECT_TRUE(HasSpan(option5.name(0))); + EXPECT_TRUE(HasSpan(option6.name(0))); + EXPECT_TRUE(HasSpan(option2.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option3.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option4.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option5.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option6.name(0), "name_part")); +} + +TEST_F(SourceInfoTest, ScopedOptions) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " $a$option mopt = 1;$b$\n" + "}\n" + "enum Bar {\n" + " $c$option eopt = 1;$d$\n" + "}\n" + "service Baz {\n" + " $e$option sopt = 1;$f$\n" + " rpc M(X) returns(Y) {\n" + " $g$option mopt = 1;$h$\n" + " }\n" + "}\n")); + + EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options())); + EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options())); + EXPECT_TRUE(HasSpan('e', 'f', file_.service(0).options())); + EXPECT_TRUE(HasSpan('g', 'h', file_.service(0).method(0).options())); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan(file_.enum_type(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan(file_.service(0))); + EXPECT_TRUE(HasSpan(file_.service(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0))); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0), "positive_int_value")); +} + +TEST_F(SourceInfoTest, FieldOptions) { + // The actual "name = value" pairs are parsed by the same code as for + // top-level options so we won't re-test that -- just make sure that the + // syntax used for field options is understood. + EXPECT_TRUE(Parse( + "message Foo {" + " optional int32 bar = 1 " + "$a$[default=$b$123$c$,$d$opt1=123$e$," + "$f$opt2='hi'$g$]$h$;" + "}\n" + )); + + const FieldDescriptorProto& field = file_.message_type(0).field(0); + const UninterpretedOption& option1 = field.options().uninterpreted_option(0); + const UninterpretedOption& option2 = field.options().uninterpreted_option(1); + + EXPECT_TRUE(HasSpan('a', 'h', field.options())); + EXPECT_TRUE(HasSpan('b', 'c', field, "default_value")); + EXPECT_TRUE(HasSpan('d', 'e', option1)); + EXPECT_TRUE(HasSpan('f', 'g', option2)); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan(field)); + EXPECT_TRUE(HasSpan(field, "label")); + EXPECT_TRUE(HasSpan(field, "type")); + EXPECT_TRUE(HasSpan(field, "name")); + EXPECT_TRUE(HasSpan(field, "number")); + EXPECT_TRUE(HasSpan(option1, "name")); + EXPECT_TRUE(HasSpan(option2, "name")); + EXPECT_TRUE(HasSpan(option1.name(0))); + EXPECT_TRUE(HasSpan(option2.name(0))); + EXPECT_TRUE(HasSpan(option1.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option2.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option1, "positive_int_value")); + EXPECT_TRUE(HasSpan(option2, "string_value")); +} + +TEST_F(SourceInfoTest, EnumValueOptions) { + // The actual "name = value" pairs are parsed by the same code as for + // top-level options so we won't re-test that -- just make sure that the + // syntax used for enum options is understood. + EXPECT_TRUE(Parse( + "enum Foo {" + " BAR = 1 $a$[$b$opt1=123$c$,$d$opt2='hi'$e$]$f$;" + "}\n" + )); + + const EnumValueDescriptorProto& value = file_.enum_type(0).value(0); + const UninterpretedOption& option1 = value.options().uninterpreted_option(0); + const UninterpretedOption& option2 = value.options().uninterpreted_option(1); + + EXPECT_TRUE(HasSpan('a', 'f', value.options())); + EXPECT_TRUE(HasSpan('b', 'c', option1)); + EXPECT_TRUE(HasSpan('d', 'e', option2)); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.enum_type(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); + EXPECT_TRUE(HasSpan(value)); + EXPECT_TRUE(HasSpan(value, "name")); + EXPECT_TRUE(HasSpan(value, "number")); + EXPECT_TRUE(HasSpan(option1, "name")); + EXPECT_TRUE(HasSpan(option2, "name")); + EXPECT_TRUE(HasSpan(option1.name(0))); + EXPECT_TRUE(HasSpan(option2.name(0))); + EXPECT_TRUE(HasSpan(option1.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option2.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option1, "positive_int_value")); + EXPECT_TRUE(HasSpan(option2, "string_value")); +} + +TEST_F(SourceInfoTest, DocComments) { + EXPECT_TRUE(Parse( + "// Foo leading\n" + "// line 2\n" + "$a$message Foo {\n" + " // Foo trailing\n" + " // line 2\n" + "\n" + " // ignored\n" + "\n" + " // bar leading\n" + " $b$optional int32 bar = 1;$c$\n" + " // bar trailing\n" + "}$d$\n" + "// ignored\n" + )); + + const DescriptorProto& foo = file_.message_type(0); + const FieldDescriptorProto& bar = foo.field(0); + + EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, + " Foo leading\n line 2\n", + " Foo trailing\n line 2\n")); + EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, + " bar leading\n", + " bar trailing\n")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(foo, "name")); + EXPECT_TRUE(HasSpan(bar, "label")); + EXPECT_TRUE(HasSpan(bar, "type")); + EXPECT_TRUE(HasSpan(bar, "name")); + EXPECT_TRUE(HasSpan(bar, "number")); +} + +TEST_F(SourceInfoTest, DocComments2) { + EXPECT_TRUE(Parse( + "// ignored\n" + "syntax = \"proto2\";\n" + "// Foo leading\n" + "// line 2\n" + "$a$message Foo {\n" + " /* Foo trailing\n" + " * line 2 */\n" + " // ignored\n" + " /* bar leading\n" + " */" + " $b$optional int32 bar = 1;$c$ // bar trailing\n" + " // ignored\n" + "}$d$\n" + "// ignored\n" + "\n" + "// option leading\n" + "$e$option baz = 123;$f$\n" + "// option trailing\n" + )); + + const DescriptorProto& foo = file_.message_type(0); + const FieldDescriptorProto& bar = foo.field(0); + const UninterpretedOption& baz = file_.options().uninterpreted_option(0); + + EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, + " Foo leading\n line 2\n", + " Foo trailing\n line 2 ")); + EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, + " bar leading\n", + " bar trailing\n")); + EXPECT_TRUE(HasSpanWithComment('e', 'f', baz, + " option leading\n", + " option trailing\n")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(foo, "name")); + EXPECT_TRUE(HasSpan(bar, "label")); + EXPECT_TRUE(HasSpan(bar, "type")); + EXPECT_TRUE(HasSpan(bar, "name")); + EXPECT_TRUE(HasSpan(bar, "number")); + EXPECT_TRUE(HasSpan(file_.options())); + EXPECT_TRUE(HasSpan(baz, "name")); + EXPECT_TRUE(HasSpan(baz.name(0))); + EXPECT_TRUE(HasSpan(baz.name(0), "name_part")); + EXPECT_TRUE(HasSpan(baz, "positive_int_value")); +} + +TEST_F(SourceInfoTest, DocComments3) { + EXPECT_TRUE(Parse( + "$a$message Foo {\n" + " // bar leading\n" + " $b$optional int32 bar = 1 [(baz.qux) = {}];$c$\n" + " // bar trailing\n" + "}$d$\n" + "// ignored\n" + )); + + const DescriptorProto& foo = file_.message_type(0); + const FieldDescriptorProto& bar = foo.field(0); + + EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, + " bar leading\n", + " bar trailing\n")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(foo)); + EXPECT_TRUE(HasSpan(foo, "name")); + EXPECT_TRUE(HasSpan(bar, "label")); + EXPECT_TRUE(HasSpan(bar, "type")); + EXPECT_TRUE(HasSpan(bar, "name")); + EXPECT_TRUE(HasSpan(bar, "number")); + EXPECT_TRUE(HasSpan(bar.options())); + EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan( + bar.options().uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan( + bar.options().uninterpreted_option(0), "aggregate_value")); +} + +TEST_F(SourceInfoTest, DocCommentsOneof) { + EXPECT_TRUE(Parse( + "// ignored\n" + "syntax = \"proto2\";\n" + "// Foo leading\n" + "$a$message Foo {\n" + " /* Foo trailing\n" + " */\n" + " // ignored\n" + " /* bar leading\n" + " * line 2 */\n" + " $b$oneof bar {\n" + " /* bar trailing\n" + " * line 2 */\n" + " // ignored\n" + " /* bar_int leading\n" + " */\n" + " $c$int32 bar_int = 1;$d$ // bar_int trailing\n" + " // ignored\n" + " }$e$\n" + "}$f$\n")); + + const DescriptorProto& foo = file_.message_type(0); + const OneofDescriptorProto& bar = foo.oneof_decl(0); + const FieldDescriptorProto& bar_int = foo.field(0); + + EXPECT_TRUE(HasSpanWithComment('a', 'f', foo, + " Foo leading\n", + " Foo trailing\n")); + EXPECT_TRUE(HasSpanWithComment('b', 'e', bar, + " bar leading\n line 2 ", + " bar trailing\n line 2 ")); + EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int, + " bar_int leading\n", + " bar_int trailing\n")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(foo, "name")); + EXPECT_TRUE(HasSpan(bar, "name")); + EXPECT_TRUE(HasSpan(bar_int, "type")); + EXPECT_TRUE(HasSpan(bar_int, "name")); + EXPECT_TRUE(HasSpan(bar_int, "number")); +} + // =================================================================== } // anonymous namespace diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc index a4aedaf..727f942 100644 --- a/src/google/protobuf/compiler/plugin.cc +++ b/src/google/protobuf/compiler/plugin.cc @@ -59,13 +59,15 @@ namespace google { namespace protobuf { namespace compiler { -class GeneratorResponseOutputDirectory : public OutputDirectory { +class GeneratorResponseContext : public GeneratorContext { public: - GeneratorResponseOutputDirectory(CodeGeneratorResponse* response) - : response_(response) {} - virtual ~GeneratorResponseOutputDirectory() {} + GeneratorResponseContext(CodeGeneratorResponse* response, + const vector& parsed_files) + : response_(response), + parsed_files_(parsed_files) {} + virtual ~GeneratorResponseContext() {} - // implements OutputDirectory -------------------------------------- + // implements GeneratorContext -------------------------------------- virtual io::ZeroCopyOutputStream* Open(const string& filename) { CodeGeneratorResponse::File* file = response_->add_file(); @@ -81,8 +83,13 @@ class GeneratorResponseOutputDirectory : public OutputDirectory { return new io::StringOutputStream(file->mutable_content()); } + void ListParsedFiles(vector* output) { + *output = parsed_files_; + } + private: CodeGeneratorResponse* response_; + const vector& parsed_files_; }; int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { @@ -112,22 +119,26 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { } } - CodeGeneratorResponse response; - GeneratorResponseOutputDirectory output_directory(&response); - + vector parsed_files; for (int i = 0; i < request.file_to_generate_size(); i++) { - const FileDescriptor* file = - pool.FindFileByName(request.file_to_generate(i)); - if (file == NULL) { + parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i))); + if (parsed_files.back() == NULL) { cerr << argv[0] << ": protoc asked plugin to generate a file but " "did not provide a descriptor for the file: " << request.file_to_generate(i) << endl; return 1; } + } + + CodeGeneratorResponse response; + GeneratorResponseContext context(&response, parsed_files); + + for (int i = 0; i < parsed_files.size(); i++) { + const FileDescriptor* file = parsed_files[i]; string error; bool succeeded = generator->Generate( - file, request.parameter(), &output_directory, &error); + file, request.parameter(), &context, &error); if (!succeeded && error.empty()) { error = "Code generator returned false but provided no error " diff --git a/src/google/protobuf/compiler/plugin.h b/src/google/protobuf/compiler/plugin.h index 7c40333..6fa2de1 100644 --- a/src/google/protobuf/compiler/plugin.h +++ b/src/google/protobuf/compiler/plugin.h @@ -56,7 +56,6 @@ #define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__ #include - namespace google { namespace protobuf { namespace compiler { diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 6b0dd55..b5cd01b 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -1,11 +1,17 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/compiler/plugin.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include "google/protobuf/compiler/plugin.pb.h" + +#include + +#include #include #include #include #include +#include #include #include // @@protoc_insertion_point(includes) @@ -133,7 +139,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { "atorResponse\022\r\n\005error\030\001 \001(\t\022B\n\004file\030\017 \003(" "\01324.google.protobuf.compiler.CodeGenerat" "orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n" - "\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\t", 399); + "\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\tB" + ",\n\034com.google.protobuf.compilerB\014PluginP" + "rotos", 445); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes); CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest(); @@ -152,10 +160,8 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto } } static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_; - // =================================================================== -const ::std::string CodeGeneratorRequest::_default_parameter_; #ifndef _MSC_VER const int CodeGeneratorRequest::kFileToGenerateFieldNumber; const int CodeGeneratorRequest::kParameterFieldNumber; @@ -165,6 +171,7 @@ const int CodeGeneratorRequest::kProtoFileFieldNumber; CodeGeneratorRequest::CodeGeneratorRequest() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest) } void CodeGeneratorRequest::InitAsDefaultInstance() { @@ -174,20 +181,23 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest) } void CodeGeneratorRequest::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - parameter_ = const_cast< ::std::string*>(&_default_parameter_); + parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } CodeGeneratorRequest::~CodeGeneratorRequest() { + // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorRequest) SharedDtor(); } void CodeGeneratorRequest::SharedDtor() { - if (parameter_ != &_default_parameter_) { + if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete parameter_; } if (this != default_instance_) { @@ -205,7 +215,8 @@ const ::google::protobuf::Descriptor* CodeGeneratorRequest::descriptor() { } const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + return *default_instance_; } CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL; @@ -215,11 +226,9 @@ CodeGeneratorRequest* CodeGeneratorRequest::New() const { } void CodeGeneratorRequest::Clear() { - if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { - if (_has_bit(1)) { - if (parameter_ != &_default_parameter_) { - parameter_->clear(); - } + if (has_parameter()) { + if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + parameter_->clear(); } } file_to_generate_.Clear(); @@ -230,65 +239,70 @@ void CodeGeneratorRequest::Clear() { bool CodeGeneratorRequest::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorRequest) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated string file_to_generate = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { parse_file_to_generate: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->add_file_to_generate())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( - this->file_to_generate(0).data(), this->file_to_generate(0).length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->file_to_generate(this->file_to_generate_size() - 1).data(), + this->file_to_generate(this->file_to_generate_size() - 1).length(), + ::google::protobuf::internal::WireFormat::PARSE, + "file_to_generate"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(10)) goto parse_file_to_generate; if (input->ExpectTag(18)) goto parse_parameter; break; } - + // optional string parameter = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_parameter: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_parameter())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->parameter().data(), this->parameter().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "parameter"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(122)) goto parse_proto_file; break; } - + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; case 15: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 122) { parse_proto_file: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_proto_file())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(122)) goto parse_proto_file; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -296,80 +310,93 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorRequest) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorRequest) + return false; #undef DO_ } void CodeGeneratorRequest::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorRequest) // repeated string file_to_generate = 1; for (int i = 0; i < this->file_to_generate_size(); i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->file_to_generate(i).data(), this->file_to_generate(i).length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "file_to_generate"); ::google::protobuf::internal::WireFormatLite::WriteString( 1, this->file_to_generate(i), output); } - + // optional string parameter = 2; - if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_parameter()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->parameter().data(), this->parameter().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "parameter"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 2, this->parameter(), output); } - + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; for (int i = 0; i < this->proto_file_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 15, this->proto_file(i), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorRequest) } ::google::protobuf::uint8* CodeGeneratorRequest::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest) // repeated string file_to_generate = 1; for (int i = 0; i < this->file_to_generate_size(); i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->file_to_generate(i).data(), this->file_to_generate(i).length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "file_to_generate"); target = ::google::protobuf::internal::WireFormatLite:: WriteStringToArray(1, this->file_to_generate(i), target); } - + // optional string parameter = 2; - if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_parameter()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->parameter().data(), this->parameter().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "parameter"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 2, this->parameter(), target); } - + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; for (int i = 0; i < this->proto_file_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 15, this->proto_file(i), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorRequest) return target; } int CodeGeneratorRequest::ByteSize() const { int total_size = 0; - + if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { // optional string parameter = 2; if (has_parameter()) { @@ -377,7 +404,7 @@ int CodeGeneratorRequest::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->parameter()); } - + } // repeated string file_to_generate = 1; total_size += 1 * this->file_to_generate_size(); @@ -385,7 +412,7 @@ int CodeGeneratorRequest::ByteSize() const { total_size += ::google::protobuf::internal::WireFormatLite::StringSize( this->file_to_generate(i)); } - + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; total_size += 1 * this->proto_file_size(); for (int i = 0; i < this->proto_file_size(); i++) { @@ -393,7 +420,7 @@ int CodeGeneratorRequest::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->proto_file(i)); } - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -422,7 +449,7 @@ void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) { file_to_generate_.MergeFrom(from.file_to_generate_); proto_file_.MergeFrom(from.proto_file_); if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) { - if (from._has_bit(1)) { + if (from.has_parameter()) { set_parameter(from.parameter()); } } @@ -442,10 +469,8 @@ void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) { } bool CodeGeneratorRequest::IsInitialized() const { - - for (int i = 0; i < proto_file_size(); i++) { - if (!this->proto_file(i).IsInitialized()) return false; - } + + if (!::google::protobuf::internal::AllAreInitialized(this->proto_file())) return false; return true; } @@ -471,9 +496,6 @@ void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) { // =================================================================== -const ::std::string CodeGeneratorResponse_File::_default_name_; -const ::std::string CodeGeneratorResponse_File::_default_insertion_point_; -const ::std::string CodeGeneratorResponse_File::_default_content_; #ifndef _MSC_VER const int CodeGeneratorResponse_File::kNameFieldNumber; const int CodeGeneratorResponse_File::kInsertionPointFieldNumber; @@ -483,6 +505,7 @@ const int CodeGeneratorResponse_File::kContentFieldNumber; CodeGeneratorResponse_File::CodeGeneratorResponse_File() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } void CodeGeneratorResponse_File::InitAsDefaultInstance() { @@ -492,28 +515,31 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } void CodeGeneratorResponse_File::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); - insertion_point_ = const_cast< ::std::string*>(&_default_insertion_point_); - content_ = const_cast< ::std::string*>(&_default_content_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } CodeGeneratorResponse_File::~CodeGeneratorResponse_File() { + // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse.File) SharedDtor(); } void CodeGeneratorResponse_File::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } - if (insertion_point_ != &_default_insertion_point_) { + if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete insertion_point_; } - if (content_ != &_default_content_) { + if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete content_; } if (this != default_instance_) { @@ -531,7 +557,8 @@ const ::google::protobuf::Descriptor* CodeGeneratorResponse_File::descriptor() { } const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + return *default_instance_; } CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL; @@ -541,19 +568,19 @@ CodeGeneratorResponse_File* CodeGeneratorResponse_File::New() const { } void CodeGeneratorResponse_File::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (_has_bits_[0 / 32] & 7) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } - if (_has_bit(1)) { - if (insertion_point_ != &_default_insertion_point_) { + if (has_insertion_point()) { + if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { insertion_point_->clear(); } } - if (_has_bit(2)) { - if (content_ != &_default_content_) { + if (has_content()) { + if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { content_->clear(); } } @@ -564,65 +591,70 @@ void CodeGeneratorResponse_File::Clear() { bool CodeGeneratorResponse_File::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse.File) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_insertion_point; break; } - + // optional string insertion_point = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_insertion_point: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_insertion_point())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->insertion_point().data(), this->insertion_point().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "insertion_point"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(122)) goto parse_content; break; } - + // optional string content = 15; case 15: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 122) { parse_content: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_content())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->content().data(), this->content().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "content"); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -630,87 +662,102 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorResponse.File) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorResponse.File) + return false; #undef DO_ } void CodeGeneratorResponse_File::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorResponse.File) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } - + // optional string insertion_point = 2; - if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_insertion_point()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->insertion_point().data(), this->insertion_point().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "insertion_point"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 2, this->insertion_point(), output); } - + // optional string content = 15; - if (_has_bit(2)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_content()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->content().data(), this->content().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "content"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 15, this->content(), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse.File) } ::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); } - + // optional string insertion_point = 2; - if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_insertion_point()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->insertion_point().data(), this->insertion_point().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "insertion_point"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 2, this->insertion_point(), target); } - + // optional string content = 15; - if (_has_bit(2)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_content()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->content().data(), this->content().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "content"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 15, this->content(), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse.File) return target; } int CodeGeneratorResponse_File::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional string name = 1; if (has_name()) { @@ -718,21 +765,21 @@ int CodeGeneratorResponse_File::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->name()); } - + // optional string insertion_point = 2; if (has_insertion_point()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->insertion_point()); } - + // optional string content = 15; if (has_content()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->content()); } - + } if (!unknown_fields().empty()) { total_size += @@ -760,13 +807,13 @@ void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& fr void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(1)) { + if (from.has_insertion_point()) { set_insertion_point(from.insertion_point()); } - if (from._has_bit(2)) { + if (from.has_content()) { set_content(from.content()); } } @@ -786,7 +833,7 @@ void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from } bool CodeGeneratorResponse_File::IsInitialized() const { - + return true; } @@ -812,7 +859,6 @@ void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) { // ------------------------------------------------------------------- -const ::std::string CodeGeneratorResponse::_default_error_; #ifndef _MSC_VER const int CodeGeneratorResponse::kErrorFieldNumber; const int CodeGeneratorResponse::kFileFieldNumber; @@ -821,6 +867,7 @@ const int CodeGeneratorResponse::kFileFieldNumber; CodeGeneratorResponse::CodeGeneratorResponse() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse) } void CodeGeneratorResponse::InitAsDefaultInstance() { @@ -830,20 +877,23 @@ CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse) } void CodeGeneratorResponse::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - error_ = const_cast< ::std::string*>(&_default_error_); + error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } CodeGeneratorResponse::~CodeGeneratorResponse() { + // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse) SharedDtor(); } void CodeGeneratorResponse::SharedDtor() { - if (error_ != &_default_error_) { + if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete error_; } if (this != default_instance_) { @@ -861,7 +911,8 @@ const ::google::protobuf::Descriptor* CodeGeneratorResponse::descriptor() { } const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + return *default_instance_; } CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL; @@ -871,11 +922,9 @@ CodeGeneratorResponse* CodeGeneratorResponse::New() const { } void CodeGeneratorResponse::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (error_ != &_default_error_) { - error_->clear(); - } + if (has_error()) { + if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + error_->clear(); } } file_.Clear(); @@ -885,46 +934,50 @@ void CodeGeneratorResponse::Clear() { bool CodeGeneratorResponse::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string error = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_error())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->error().data(), this->error().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "error"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(122)) goto parse_file; break; } - + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; case 15: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 122) { parse_file: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_file())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(122)) goto parse_file; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -932,62 +985,73 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorResponse) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorResponse) + return false; #undef DO_ } void CodeGeneratorResponse::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorResponse) // optional string error = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_error()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->error().data(), this->error().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "error"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->error(), output); } - + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; for (int i = 0; i < this->file_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 15, this->file(i), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse) } ::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse) // optional string error = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_error()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->error().data(), this->error().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "error"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->error(), target); } - + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; for (int i = 0; i < this->file_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 15, this->file(i), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse) return target; } int CodeGeneratorResponse::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional string error = 1; if (has_error()) { @@ -995,7 +1059,7 @@ int CodeGeneratorResponse::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->error()); } - + } // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; total_size += 1 * this->file_size(); @@ -1004,7 +1068,7 @@ int CodeGeneratorResponse::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->file(i)); } - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -1032,7 +1096,7 @@ void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) { GOOGLE_CHECK_NE(&from, this); file_.MergeFrom(from.file_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_error()) { set_error(from.error()); } } @@ -1052,7 +1116,7 @@ void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) { } bool CodeGeneratorResponse::IsInitialized() const { - + return true; } diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index f8f8053..815addd 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -8,21 +8,22 @@ #include -#if GOOGLE_PROTOBUF_VERSION < 2003000 +#if GOOGLE_PROTOBUF_VERSION < 2006000 #error This file was generated by a newer version of protoc which is #error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 2003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 2006000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is #error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif #include +#include #include #include -#include +#include #include "google/protobuf/descriptor.pb.h" // @@protoc_insertion_point(includes) @@ -45,29 +46,29 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message public: CodeGeneratorRequest(); virtual ~CodeGeneratorRequest(); - + CodeGeneratorRequest(const CodeGeneratorRequest& from); - + inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const CodeGeneratorRequest& default_instance(); - + void Swap(CodeGeneratorRequest* other); - + // implements Message ---------------------------------------------- - + CodeGeneratorRequest* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -75,7 +76,7 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message void MergeFrom(const CodeGeneratorRequest& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -88,13 +89,12 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // repeated string file_to_generate = 1; inline int file_to_generate_size() const; inline void clear_file_to_generate(); @@ -110,7 +110,7 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message inline void add_file_to_generate(const char* value, size_t size); inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const; inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate(); - + // optional string parameter = 2; inline bool has_parameter() const; inline void clear_parameter(); @@ -120,7 +120,9 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message inline void set_parameter(const char* value); inline void set_parameter(const char* value, size_t size); inline ::std::string* mutable_parameter(); - + inline ::std::string* release_parameter(); + inline void set_allocated_parameter(::std::string* parameter); + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; inline int proto_file_size() const; inline void clear_proto_file(); @@ -132,33 +134,23 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message proto_file() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_proto_file(); - + // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) private: + inline void set_has_parameter(); + inline void clear_has_parameter(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_; ::std::string* parameter_; - static const ::std::string _default_parameter_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_; friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static CodeGeneratorRequest* default_instance_; }; @@ -168,29 +160,29 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M public: CodeGeneratorResponse_File(); virtual ~CodeGeneratorResponse_File(); - + CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from); - + inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const CodeGeneratorResponse_File& default_instance(); - + void Swap(CodeGeneratorResponse_File* other); - + // implements Message ---------------------------------------------- - + CodeGeneratorResponse_File* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -198,7 +190,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M void MergeFrom(const CodeGeneratorResponse_File& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -211,13 +203,12 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // optional string name = 1; inline bool has_name() const; inline void clear_name(); @@ -227,7 +218,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M inline void set_name(const char* value); inline void set_name(const char* value, size_t size); inline ::std::string* mutable_name(); - + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + // optional string insertion_point = 2; inline bool has_insertion_point() const; inline void clear_insertion_point(); @@ -237,7 +230,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M inline void set_insertion_point(const char* value); inline void set_insertion_point(const char* value, size_t size); inline ::std::string* mutable_insertion_point(); - + inline ::std::string* release_insertion_point(); + inline void set_allocated_insertion_point(::std::string* insertion_point); + // optional string content = 15; inline bool has_content() const; inline void clear_content(); @@ -247,35 +242,29 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M inline void set_content(const char* value); inline void set_content(const char* value, size_t size); inline ::std::string* mutable_content(); - + inline ::std::string* release_content(); + inline void set_allocated_content(::std::string* content); + // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_insertion_point(); + inline void clear_has_insertion_point(); + inline void set_has_content(); + inline void clear_has_content(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::std::string* name_; - static const ::std::string _default_name_; ::std::string* insertion_point_; - static const ::std::string _default_insertion_point_; ::std::string* content_; - static const ::std::string _default_content_; friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static CodeGeneratorResponse_File* default_instance_; }; @@ -285,29 +274,29 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag public: CodeGeneratorResponse(); virtual ~CodeGeneratorResponse(); - + CodeGeneratorResponse(const CodeGeneratorResponse& from); - + inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const CodeGeneratorResponse& default_instance(); - + void Swap(CodeGeneratorResponse* other); - + // implements Message ---------------------------------------------- - + CodeGeneratorResponse* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -315,7 +304,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag void MergeFrom(const CodeGeneratorResponse& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -328,15 +317,14 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + typedef CodeGeneratorResponse_File File; - + // accessors ------------------------------------------------------- - + // optional string error = 1; inline bool has_error() const; inline void clear_error(); @@ -346,7 +334,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag inline void set_error(const char* value); inline void set_error(const char* value, size_t size); inline ::std::string* mutable_error(); - + inline ::std::string* release_error(); + inline void set_allocated_error(::std::string* error); + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; inline int file_size() const; inline void clear_file(); @@ -358,32 +348,22 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag file() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* mutable_file(); - + // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) private: + inline void set_has_error(); + inline void clear_has_error(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::std::string* error_; - static const ::std::string _default_error_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_; friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static CodeGeneratorResponse* default_instance_; }; @@ -402,83 +382,127 @@ inline void CodeGeneratorRequest::clear_file_to_generate() { file_to_generate_.Clear(); } inline const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return file_to_generate_.Get(index); } inline ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return file_to_generate_.Mutable(index); } inline void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) file_to_generate_.Mutable(index)->assign(value); } inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) { file_to_generate_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) { file_to_generate_.Mutable(index)->assign( reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline ::std::string* CodeGeneratorRequest::add_file_to_generate() { return file_to_generate_.Add(); } inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) { file_to_generate_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::add_file_to_generate(const char* value) { file_to_generate_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) { file_to_generate_.Add()->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline const ::google::protobuf::RepeatedPtrField< ::std::string>& CodeGeneratorRequest::file_to_generate() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return file_to_generate_; } inline ::google::protobuf::RepeatedPtrField< ::std::string>* CodeGeneratorRequest::mutable_file_to_generate() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return &file_to_generate_; } // optional string parameter = 2; inline bool CodeGeneratorRequest::has_parameter() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void CodeGeneratorRequest::set_has_parameter() { + _has_bits_[0] |= 0x00000002u; +} +inline void CodeGeneratorRequest::clear_has_parameter() { + _has_bits_[0] &= ~0x00000002u; } inline void CodeGeneratorRequest::clear_parameter() { - if (parameter_ != &_default_parameter_) { + if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { parameter_->clear(); } - _clear_bit(1); + clear_has_parameter(); } inline const ::std::string& CodeGeneratorRequest::parameter() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter) return *parameter_; } inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) { - _set_bit(1); - if (parameter_ == &_default_parameter_) { + set_has_parameter(); + if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { parameter_ = new ::std::string; } parameter_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline void CodeGeneratorRequest::set_parameter(const char* value) { - _set_bit(1); - if (parameter_ == &_default_parameter_) { + set_has_parameter(); + if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { parameter_ = new ::std::string; } parameter_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) { - _set_bit(1); - if (parameter_ == &_default_parameter_) { + set_has_parameter(); + if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { parameter_ = new ::std::string; } parameter_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline ::std::string* CodeGeneratorRequest::mutable_parameter() { - _set_bit(1); - if (parameter_ == &_default_parameter_) { + set_has_parameter(); + if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { parameter_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter) return parameter_; } +inline ::std::string* CodeGeneratorRequest::release_parameter() { + clear_has_parameter(); + if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = parameter_; + parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) { + if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete parameter_; + } + if (parameter) { + set_has_parameter(); + parameter_ = parameter; + } else { + clear_has_parameter(); + parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter) +} // repeated .google.protobuf.FileDescriptorProto proto_file = 15; inline int CodeGeneratorRequest::proto_file_size() const { @@ -488,20 +512,25 @@ inline void CodeGeneratorRequest::clear_proto_file() { proto_file_.Clear(); } inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_.Get(index); } inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_.Mutable(index); } inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() { + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& CodeGeneratorRequest::proto_file() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* CodeGeneratorRequest::mutable_proto_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return &proto_file_; } @@ -511,129 +540,231 @@ CodeGeneratorRequest::mutable_proto_file() { // optional string name = 1; inline bool CodeGeneratorResponse_File::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void CodeGeneratorResponse_File::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void CodeGeneratorResponse_File::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void CodeGeneratorResponse_File::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& CodeGeneratorResponse_File::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name) return *name_; } inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline void CodeGeneratorResponse_File::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline ::std::string* CodeGeneratorResponse_File::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name) return name_; } +inline ::std::string* CodeGeneratorResponse_File::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name) +} // optional string insertion_point = 2; inline bool CodeGeneratorResponse_File::has_insertion_point() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void CodeGeneratorResponse_File::set_has_insertion_point() { + _has_bits_[0] |= 0x00000002u; +} +inline void CodeGeneratorResponse_File::clear_has_insertion_point() { + _has_bits_[0] &= ~0x00000002u; } inline void CodeGeneratorResponse_File::clear_insertion_point() { - if (insertion_point_ != &_default_insertion_point_) { + if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { insertion_point_->clear(); } - _clear_bit(1); + clear_has_insertion_point(); } inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) return *insertion_point_; } inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) { - _set_bit(1); - if (insertion_point_ == &_default_insertion_point_) { + set_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { insertion_point_ = new ::std::string; } insertion_point_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) { - _set_bit(1); - if (insertion_point_ == &_default_insertion_point_) { + set_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { insertion_point_ = new ::std::string; } insertion_point_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) { - _set_bit(1); - if (insertion_point_ == &_default_insertion_point_) { + set_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { insertion_point_ = new ::std::string; } insertion_point_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() { - _set_bit(1); - if (insertion_point_ == &_default_insertion_point_) { + set_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { insertion_point_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) return insertion_point_; } +inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() { + clear_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = insertion_point_; + insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) { + if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete insertion_point_; + } + if (insertion_point) { + set_has_insertion_point(); + insertion_point_ = insertion_point; + } else { + clear_has_insertion_point(); + insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) +} // optional string content = 15; inline bool CodeGeneratorResponse_File::has_content() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void CodeGeneratorResponse_File::set_has_content() { + _has_bits_[0] |= 0x00000004u; +} +inline void CodeGeneratorResponse_File::clear_has_content() { + _has_bits_[0] &= ~0x00000004u; } inline void CodeGeneratorResponse_File::clear_content() { - if (content_ != &_default_content_) { + if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { content_->clear(); } - _clear_bit(2); + clear_has_content(); } inline const ::std::string& CodeGeneratorResponse_File::content() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content) return *content_; } inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) { - _set_bit(2); - if (content_ == &_default_content_) { + set_has_content(); + if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { content_ = new ::std::string; } content_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline void CodeGeneratorResponse_File::set_content(const char* value) { - _set_bit(2); - if (content_ == &_default_content_) { + set_has_content(); + if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { content_ = new ::std::string; } content_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) { - _set_bit(2); - if (content_ == &_default_content_) { + set_has_content(); + if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { content_ = new ::std::string; } content_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline ::std::string* CodeGeneratorResponse_File::mutable_content() { - _set_bit(2); - if (content_ == &_default_content_) { + set_has_content(); + if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { content_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content) return content_; } +inline ::std::string* CodeGeneratorResponse_File::release_content() { + clear_has_content(); + if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = content_; + content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) { + if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete content_; + } + if (content) { + set_has_content(); + content_ = content; + } else { + clear_has_content(); + content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content) +} // ------------------------------------------------------------------- @@ -641,45 +772,79 @@ inline ::std::string* CodeGeneratorResponse_File::mutable_content() { // optional string error = 1; inline bool CodeGeneratorResponse::has_error() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void CodeGeneratorResponse::set_has_error() { + _has_bits_[0] |= 0x00000001u; +} +inline void CodeGeneratorResponse::clear_has_error() { + _has_bits_[0] &= ~0x00000001u; } inline void CodeGeneratorResponse::clear_error() { - if (error_ != &_default_error_) { + if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { error_->clear(); } - _clear_bit(0); + clear_has_error(); } inline const ::std::string& CodeGeneratorResponse::error() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error) return *error_; } inline void CodeGeneratorResponse::set_error(const ::std::string& value) { - _set_bit(0); - if (error_ == &_default_error_) { + set_has_error(); + if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { error_ = new ::std::string; } error_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error) } inline void CodeGeneratorResponse::set_error(const char* value) { - _set_bit(0); - if (error_ == &_default_error_) { + set_has_error(); + if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { error_ = new ::std::string; } error_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error) } inline void CodeGeneratorResponse::set_error(const char* value, size_t size) { - _set_bit(0); - if (error_ == &_default_error_) { + set_has_error(); + if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { error_ = new ::std::string; } error_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error) } inline ::std::string* CodeGeneratorResponse::mutable_error() { - _set_bit(0); - if (error_ == &_default_error_) { + set_has_error(); + if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { error_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error) return error_; } +inline ::std::string* CodeGeneratorResponse::release_error() { + clear_has_error(); + if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = error_; + error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) { + if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete error_; + } + if (error) { + set_has_error(); + error_ = error; + } else { + clear_has_error(); + error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error) +} // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; inline int CodeGeneratorResponse::file_size() const { @@ -689,20 +854,25 @@ inline void CodeGeneratorResponse::clear_file() { file_.Clear(); } inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file) return file_.Get(index); } inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file) return file_.Mutable(index); } inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() { + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file) return file_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& CodeGeneratorResponse::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file) return file_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* CodeGeneratorResponse::mutable_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file) return &file_; } diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto index 4e928b0..77b888f 100644 --- a/src/google/protobuf/compiler/plugin.proto +++ b/src/google/protobuf/compiler/plugin.proto @@ -45,6 +45,8 @@ // flag "--${NAME}_out" is passed to protoc. package google.protobuf.compiler; +option java_package = "com.google.protobuf.compiler"; +option java_outer_classname = "PluginProtos"; import "google/protobuf/descriptor.proto"; @@ -131,7 +133,7 @@ message CodeGeneratorResponse { // in order to work correctly in that context. // // The code generator that generates the initial file and the one which - // inserts into it must both run as part of a single invocatino of protoc. + // inserts into it must both run as part of a single invocation of protoc. // Code generators are executed in the order in which they appear on the // command line. // diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index fae83a3..113873a 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -28,6 +28,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +//#PY25 compatible generated code for GAE. +// Copyright 2007 Google Inc. All Rights Reserved. // Author: robinson@google.com (Will Robinson) // // This module outputs pure-Python protocol message classes that will @@ -45,6 +47,7 @@ #include #include #include +#include #include #include @@ -52,6 +55,7 @@ #include #include +#include #include #include #include @@ -106,6 +110,12 @@ string NamePrefixedWithNestedTypes(const DescriptorT& descriptor, const char kDescriptorKey[] = "DESCRIPTOR"; +// Does the file have top-level enums? +inline bool HasTopLevelEnums(const FileDescriptor *file) { + return file->enum_type_count() > 0; +} + + // Should we generate generic services for this file? inline bool HasGenericServices(const FileDescriptor *file) { return file->service_count() > 0 && @@ -120,13 +130,23 @@ void PrintTopBoilerplate( // TODO(robinson): Allow parameterization of Python version? printer->Print( "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "\n" - "from google.protobuf import descriptor\n" - "from google.protobuf import message\n" - "from google.protobuf import reflection\n"); + "# source: $filename$\n" + "\nimport sys\n_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))" //##PY25 + "\n", + "filename", file->name()); + if (HasTopLevelEnums(file)) { + printer->Print( + "from google.protobuf.internal import enum_type_wrapper\n"); + } + printer->Print( + "from google.protobuf import descriptor as _descriptor\n" + "from google.protobuf import message as _message\n" + "from google.protobuf import reflection as _reflection\n" + "from google.protobuf import symbol_database as " + "_symbol_database\n"); if (HasGenericServices(file)) { printer->Print( - "from google.protobuf import service\n" + "from google.protobuf import service as _service\n" "from google.protobuf import service_reflection\n"); } @@ -136,7 +156,8 @@ void PrintTopBoilerplate( "from google.protobuf import descriptor_pb2\n"); } printer->Print( - "# @@protoc_insertion_point(imports)\n"); + "# @@protoc_insertion_point(imports)\n\n" + "_sym_db = _symbol_database.Default()\n"); printer->Print("\n\n"); } @@ -202,12 +223,12 @@ string StringifyDefaultValue(const FieldDescriptor& field) { case FieldDescriptor::CPPTYPE_ENUM: return SimpleItoa(field.default_value_enum()->number()); case FieldDescriptor::CPPTYPE_STRING: - if (field.type() == FieldDescriptor::TYPE_STRING) { - return "unicode(\"" + CEscape(field.default_value_string()) + - "\", \"utf-8\")"; - } else { - return "\"" + CEscape(field.default_value_string()) + "\""; - } +//##!PY25 return "b\"" + CEscape(field.default_value_string()) + +//##!PY25 (field.type() != FieldDescriptor::TYPE_STRING ? "\"" : +//##!PY25 "\".decode('utf-8')"); + return "_b(\"" + CEscape(field.default_value_string()) + //##PY25 + (field.type() != FieldDescriptor::TYPE_STRING ? "\")" : //##PY25 + "\").decode('utf-8')"); //##PY25 case FieldDescriptor::CPPTYPE_MESSAGE: return "None"; } @@ -230,7 +251,7 @@ Generator::~Generator() { bool Generator::Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { // Completely serialize all Generate() calls on this instance. The @@ -252,26 +273,29 @@ bool Generator::Generate(const FileDescriptor* file, fdp.SerializeToString(&file_descriptor_serialized_); - scoped_ptr output(output_directory->Open(filename)); + scoped_ptr output(context->Open(filename)); GOOGLE_CHECK(output.get()); io::Printer printer(output.get(), '$'); printer_ = &printer; PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto()); + PrintImports(); PrintFileDescriptor(); PrintTopLevelEnums(); PrintTopLevelExtensions(); PrintAllNestedEnumsInFile(); PrintMessageDescriptors(); - // We have to print the imports after the descriptors, so that mutually - // recursive protos in separate files can successfully reference each other. - PrintImports(); FixForeignFieldsInDescriptors(); PrintMessages(); // We have to fix up the extensions after the message classes themselves, // since they need to call static RegisterExtension() methods on these // classes. FixForeignFieldsInExtensions(); + // Descriptor options may have custom extensions. These custom options + // can only be successfully parsed after we register corresponding + // extensions. Therefore we parse all options again here to recognize + // custom options that may be unknown when we define the descriptors. + FixAllDescriptorOptions(); if (HasGenericServices(file)) { PrintServices(); } @@ -290,6 +314,13 @@ void Generator::PrintImports() const { module_name); } printer_->Print("\n"); + + // Print public imports. + for (int i = 0; i < file_->public_dependency_count(); ++i) { + string module_name = ModuleName(file_->public_dependency(i)->name()); + printer_->Print("from $module$ import *\n", "module", module_name); + } + printer_->Print("\n"); } // Prints the single file descriptor for this file. @@ -299,20 +330,31 @@ void Generator::PrintFileDescriptor() const { m["name"] = file_->name(); m["package"] = file_->package(); const char file_descriptor_template[] = - "$descriptor_name$ = descriptor.FileDescriptor(\n" + "$descriptor_name$ = _descriptor.FileDescriptor(\n" " name='$name$',\n" " package='$package$',\n"; printer_->Print(m, file_descriptor_template); printer_->Indent(); printer_->Print( - "serialized_pb='$value$'", +//##!PY25 "serialized_pb=b'$value$'\n", + "serialized_pb=_b('$value$')\n", //##PY25 "value", strings::CHexEscape(file_descriptor_serialized_)); + if (file_->dependency_count() != 0) { + printer_->Print(",\ndependencies=["); + for (int i = 0; i < file_->dependency_count(); ++i) { + string module_name = ModuleName(file_->dependency(i)->name()); + printer_->Print("$module_name$.DESCRIPTOR,", "module_name", module_name); + } + printer_->Print("]"); + } // TODO(falk): Also print options and fix the message_type, enum_type, // service and extension later in the generation. printer_->Outdent(); printer_->Print(")\n"); + printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name", + kDescriptorKey); printer_->Print("\n"); } @@ -323,6 +365,11 @@ void Generator::PrintTopLevelEnums() const { for (int i = 0; i < file_->enum_type_count(); ++i) { const EnumDescriptor& enum_descriptor = *file_->enum_type(i); PrintEnum(enum_descriptor); + printer_->Print("$name$ = " + "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)", + "name", enum_descriptor.name(), + "descriptor_name", + ModuleLevelDescriptorName(enum_descriptor)); printer_->Print("\n"); for (int j = 0; j < enum_descriptor.value_count(); ++j) { @@ -352,12 +399,14 @@ void Generator::PrintAllNestedEnumsInFile() const { // enum_descriptor. void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { map m; - m["descriptor_name"] = ModuleLevelDescriptorName(enum_descriptor); + string module_level_descriptor_name = + ModuleLevelDescriptorName(enum_descriptor); + m["descriptor_name"] = module_level_descriptor_name; m["name"] = enum_descriptor.name(); m["full_name"] = enum_descriptor.full_name(); m["file"] = kDescriptorKey; const char enum_descriptor_template[] = - "$descriptor_name$ = descriptor.EnumDescriptor(\n" + "$descriptor_name$ = _descriptor.EnumDescriptor(\n" " name='$name$',\n" " full_name='$full_name$',\n" " filename=None,\n" @@ -377,11 +426,13 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { printer_->Print("containing_type=None,\n"); printer_->Print("options=$options_value$,\n", "options_value", - OptionsValue("EnumOptions", CEscape(options_string))); + OptionsValue("EnumOptions", options_string)); EnumDescriptorProto edp; PrintSerializedPbInterval(enum_descriptor, edp); printer_->Outdent(); printer_->Print(")\n"); + printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name", + module_level_descriptor_name); printer_->Print("\n"); } @@ -438,7 +489,7 @@ void Generator::PrintServiceDescriptor( descriptor.options().SerializeToString(&options_string); printer_->Print( - "$service_name$ = descriptor.ServiceDescriptor(\n", + "$service_name$ = _descriptor.ServiceDescriptor(\n", "service_name", service_name); printer_->Indent(); map m; @@ -461,7 +512,6 @@ void Generator::PrintServiceDescriptor( printer_->Print("methods=[\n"); for (int i = 0; i < descriptor.method_count(); ++i) { const MethodDescriptor* method = descriptor.method(i); - string options_string; method->options().SerializeToString(&options_string); m.clear(); @@ -472,7 +522,7 @@ void Generator::PrintServiceDescriptor( m["input_type"] = ModuleLevelDescriptorName(*(method->input_type())); m["output_type"] = ModuleLevelDescriptorName(*(method->output_type())); m["options_value"] = OptionsValue("MethodOptions", options_string); - printer_->Print("descriptor.MethodDescriptor(\n"); + printer_->Print("_descriptor.MethodDescriptor(\n"); printer_->Indent(); printer_->Print( m, @@ -493,27 +543,36 @@ void Generator::PrintServiceDescriptor( void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { // Print the service. - printer_->Print("class $class_name$(service.Service):\n", + printer_->Print("$class_name$ = service_reflection.GeneratedServiceType(" + "'$class_name$', (_service.Service,), dict(\n", "class_name", descriptor.name()); printer_->Indent(); printer_->Print( - "__metaclass__ = service_reflection.GeneratedServiceType\n" - "$descriptor_key$ = $descriptor_name$\n", + "$descriptor_key$ = $descriptor_name$,\n", "descriptor_key", kDescriptorKey, "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); + printer_->Print( + "__module__ = '$module_name$'\n", + "module_name", ModuleName(file_->name())); + printer_->Print("))\n\n"); printer_->Outdent(); } void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const { // Print the service stub. - printer_->Print("class $class_name$_Stub($class_name$):\n", + printer_->Print("$class_name$_Stub = " + "service_reflection.GeneratedServiceStubType(" + "'$class_name$_Stub', ($class_name$,), dict(\n", "class_name", descriptor.name()); printer_->Indent(); printer_->Print( - "__metaclass__ = service_reflection.GeneratedServiceStubType\n" - "$descriptor_key$ = $descriptor_name$\n", + "$descriptor_key$ = $descriptor_name$,\n", "descriptor_key", kDescriptorKey, "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); + printer_->Print( + "__module__ = '$module_name$'\n", + "module_name", ModuleName(file_->name())); + printer_->Print("))\n\n"); printer_->Outdent(); } @@ -525,7 +584,7 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { PrintNestedDescriptors(message_descriptor); printer_->Print("\n"); - printer_->Print("$descriptor_name$ = descriptor.Descriptor(\n", + printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n", "descriptor_name", ModuleLevelDescriptorName(message_descriptor)); printer_->Indent(); @@ -583,7 +642,22 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { "end", SimpleItoa(range->end)); } printer_->Print("],\n"); - + printer_->Print("oneofs=[\n"); + printer_->Indent(); + for (int i = 0; i < message_descriptor.oneof_decl_count(); ++i) { + const OneofDescriptor* desc = message_descriptor.oneof_decl(i); + map m; + m["name"] = desc->name(); + m["full_name"] = desc->full_name(); + m["index"] = SimpleItoa(desc->index()); + printer_->Print( + m, + "_descriptor.OneofDescriptor(\n" + " name='$name$', full_name='$full_name$',\n" + " index=$index$, containing_type=None, fields=[]),\n"); + } + printer_->Outdent(); + printer_->Print("],\n"); // Serialization of proto DescriptorProto edp; PrintSerializedPbInterval(message_descriptor, edp); @@ -606,7 +680,12 @@ void Generator::PrintNestedDescriptors( // Prints all messages in |file|. void Generator::PrintMessages() const { for (int i = 0; i < file_->message_type_count(); ++i) { - PrintMessage(*file_->message_type(i)); + vector to_register; + PrintMessage(*file_->message_type(i), "", &to_register); + for (int j = 0; j < to_register.size(); ++j) { + printer_->Print("_sym_db.RegisterMessage($name$)\n", "name", + to_register[j]); + } printer_->Print("\n"); } } @@ -618,33 +697,40 @@ void Generator::PrintMessages() const { // reflection.py will use to construct the meat of the class itself. // // Mutually recursive with PrintNestedMessages(). -void Generator::PrintMessage( - const Descriptor& message_descriptor) const { - printer_->Print("class $name$(message.Message):\n", "name", - message_descriptor.name()); +// Collect nested message names to_register for the symbol_database. +void Generator::PrintMessage(const Descriptor& message_descriptor, + const string& prefix, + vector* to_register) const { + string qualified_name(prefix + message_descriptor.name()); + to_register->push_back(qualified_name); + printer_->Print( + "$name$ = _reflection.GeneratedProtocolMessageType('$name$', " + "(_message.Message,), dict(\n", + "name", message_descriptor.name()); printer_->Indent(); - printer_->Print("__metaclass__ = reflection.GeneratedProtocolMessageType\n"); - PrintNestedMessages(message_descriptor); + + PrintNestedMessages(message_descriptor, qualified_name + ".", to_register); map m; m["descriptor_key"] = kDescriptorKey; m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor); - printer_->Print(m, "$descriptor_key$ = $descriptor_name$\n"); - - printer_->Print( - "\n" - "# @@protoc_insertion_point(class_scope:$full_name$)\n", - "full_name", message_descriptor.full_name()); - + printer_->Print(m, "$descriptor_key$ = $descriptor_name$,\n"); + printer_->Print("__module__ = '$module_name$'\n", + "module_name", ModuleName(file_->name())); + printer_->Print("# @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", message_descriptor.full_name()); + printer_->Print("))\n"); printer_->Outdent(); } // Prints all nested messages within |containing_descriptor|. // Mutually recursive with PrintMessage(). -void Generator::PrintNestedMessages( - const Descriptor& containing_descriptor) const { +void Generator::PrintNestedMessages(const Descriptor& containing_descriptor, + const string& prefix, + vector* to_register) const { for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { printer_->Print("\n"); - PrintMessage(*containing_descriptor.nested_type(i)); + PrintMessage(*containing_descriptor.nested_type(i), prefix, to_register); + printer_->Print(",\n"); } } @@ -672,6 +758,57 @@ void Generator::FixForeignFieldsInDescriptor( const EnumDescriptor& enum_descriptor = *descriptor.enum_type(i); FixContainingTypeInDescriptor(enum_descriptor, &descriptor); } + for (int i = 0; i < descriptor.oneof_decl_count(); ++i) { + map m; + const OneofDescriptor* oneof = descriptor.oneof_decl(i); + m["descriptor_name"] = ModuleLevelDescriptorName(descriptor); + m["oneof_name"] = oneof->name(); + for (int j = 0; j < oneof->field_count(); ++j) { + m["field_name"] = oneof->field(j)->name(); + printer_->Print( + m, + "$descriptor_name$.oneofs_by_name['$oneof_name$'].fields.append(\n" + " $descriptor_name$.fields_by_name['$field_name$'])\n"); + printer_->Print( + m, + "$descriptor_name$.fields_by_name['$field_name$'].containing_oneof = " + "$descriptor_name$.oneofs_by_name['$oneof_name$']\n"); + } + } +} + +void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { + map m; + m["descriptor_name"] = kDescriptorKey; + m["message_name"] = descriptor.name(); + m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor); + const char file_descriptor_template[] = + "$descriptor_name$.message_types_by_name['$message_name$'] = " + "$message_descriptor_name$\n"; + printer_->Print(m, file_descriptor_template); +} + +void Generator::AddEnumToFileDescriptor( + const EnumDescriptor& descriptor) const { + map m; + m["descriptor_name"] = kDescriptorKey; + m["enum_name"] = descriptor.name(); + m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor); + const char file_descriptor_template[] = + "$descriptor_name$.enum_types_by_name['$enum_name$'] = " + "$enum_descriptor_name$\n"; + printer_->Print(m, file_descriptor_template); +} + +void Generator::AddExtensionToFileDescriptor( + const FieldDescriptor& descriptor) const { + map m; + m["descriptor_name"] = kDescriptorKey; + m["field_name"] = descriptor.name(); + const char file_descriptor_template[] = + "$descriptor_name$.extensions_by_name['$field_name$'] = " + "$field_name$\n"; + printer_->Print(m, file_descriptor_template); } // Sets any necessary message_type and enum_type attributes @@ -738,7 +875,7 @@ void Generator::FixContainingTypeInDescriptor( const string parent_name = ModuleLevelDescriptorName( *containing_descriptor); printer_->Print( - "$nested_name$.containing_type = $parent_name$;\n", + "$nested_name$.containing_type = $parent_name$\n", "nested_name", nested_name, "parent_name", parent_name); } @@ -752,6 +889,15 @@ void Generator::FixForeignFieldsInDescriptors() const { for (int i = 0; i < file_->message_type_count(); ++i) { FixForeignFieldsInDescriptor(*file_->message_type(i), NULL); } + for (int i = 0; i < file_->message_type_count(); ++i) { + AddMessageToFileDescriptor(*file_->message_type(i)); + } + for (int i = 0; i < file_->enum_type_count(); ++i) { + AddEnumToFileDescriptor(*file_->enum_type(i)); + } + for (int i = 0; i < file_->extension_count(); ++i) { + AddExtensionToFileDescriptor(*file_->extension(i)); + } printer_->Print("\n"); } @@ -767,6 +913,7 @@ void Generator::FixForeignFieldsInExtensions() const { for (int i = 0; i < file_->message_type_count(); ++i) { FixForeignFieldsInNestedExtensions(*file_->message_type(i)); } + printer_->Print("\n"); } void Generator::FixForeignFieldsInExtension( @@ -817,20 +964,24 @@ void Generator::PrintEnumValueDescriptor( m["options"] = OptionsValue("EnumValueOptions", options_string); printer_->Print( m, - "descriptor.EnumValueDescriptor(\n" + "_descriptor.EnumValueDescriptor(\n" " name='$name$', index=$index$, number=$number$,\n" " options=$options$,\n" " type=None)"); } +// Returns a Python expression that calls descriptor._ParseOptions using +// the given descriptor class name and serialized options protobuf string. string Generator::OptionsValue( const string& class_name, const string& serialized_options) const { if (serialized_options.length() == 0 || GeneratingDescriptorProto()) { return "None"; } else { string full_class_name = "descriptor_pb2." + class_name; - return "descriptor._ParseOptions(" + full_class_name + "(), '" - + CEscape(serialized_options)+ "')"; +//##!PY25 return "_descriptor._ParseOptions(" + full_class_name + "(), b'" +//##!PY25 + CEscape(serialized_options)+ "')"; + return "_descriptor._ParseOptions(" + full_class_name + "(), _b('" //##PY25 + + CEscape(serialized_options)+ "'))"; //##PY25 } } @@ -855,7 +1006,7 @@ void Generator::PrintFieldDescriptor( // these fields in correctly after all referenced descriptors have been // defined and/or imported (see FixForeignFieldsInDescriptors()). const char field_descriptor_decl[] = - "descriptor.FieldDescriptor(\n" + "_descriptor.FieldDescriptor(\n" " name='$name$', full_name='$full_name$', index=$index$,\n" " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n" " has_default_value=$has_default_value$, default_value=$default_value$,\n" @@ -986,6 +1137,125 @@ void Generator::PrintSerializedPbInterval( "serialized_end", SimpleItoa(offset + sp.size())); } +namespace { +void PrintDescriptorOptionsFixingCode(const string& descriptor, + const string& options, + io::Printer* printer) { + // TODO(xiaofeng): I have added a method _SetOptions() to DescriptorBase + // in proto2 python runtime but it couldn't be used here because appengine + // uses a snapshot version of the library in which the new method is not + // yet present. After appengine has synced their runtime library, the code + // below should be cleaned up to use _SetOptions(). + printer->Print( + "$descriptor$.has_options = True\n" + "$descriptor$._options = $options$\n", + "descriptor", descriptor, "options", options); +} +} // namespace + +// Prints expressions that set the options field of all descriptors. +void Generator::FixAllDescriptorOptions() const { + // Prints an expression that sets the file descriptor's options. + string file_options = OptionsValue( + "FileOptions", file_->options().SerializeAsString()); + if (file_options != "None") { + PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_); + } + // Prints expressions that set the options for all top level enums. + for (int i = 0; i < file_->enum_type_count(); ++i) { + const EnumDescriptor& enum_descriptor = *file_->enum_type(i); + FixOptionsForEnum(enum_descriptor); + } + // Prints expressions that set the options for all top level extensions. + for (int i = 0; i < file_->extension_count(); ++i) { + const FieldDescriptor& field = *file_->extension(i); + FixOptionsForField(field); + } + // Prints expressions that set the options for all messages, nested enums, + // nested extensions and message fields. + for (int i = 0; i < file_->message_type_count(); ++i) { + FixOptionsForMessage(*file_->message_type(i)); + } +} + +// Prints expressions that set the options for an enum descriptor and its +// value descriptors. +void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const { + string descriptor_name = ModuleLevelDescriptorName(enum_descriptor); + string enum_options = OptionsValue( + "EnumOptions", enum_descriptor.options().SerializeAsString()); + if (enum_options != "None") { + PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_); + } + for (int i = 0; i < enum_descriptor.value_count(); ++i) { + const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i); + string value_options = OptionsValue( + "EnumValueOptions", value_descriptor.options().SerializeAsString()); + if (value_options != "None") { + PrintDescriptorOptionsFixingCode( + StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), + value_descriptor.name().c_str()), + value_options, printer_); + } + } +} + +// Prints expressions that set the options for field descriptors (including +// extensions). +void Generator::FixOptionsForField( + const FieldDescriptor& field) const { + string field_options = OptionsValue( + "FieldOptions", field.options().SerializeAsString()); + if (field_options != "None") { + string field_name; + if (field.is_extension()) { + if (field.extension_scope() == NULL) { + // Top level extensions. + field_name = field.name(); + } else { + field_name = FieldReferencingExpression( + field.extension_scope(), field, "extensions_by_name"); + } + } else { + field_name = FieldReferencingExpression( + field.containing_type(), field, "fields_by_name"); + } + PrintDescriptorOptionsFixingCode(field_name, field_options, printer_); + } +} + +// Prints expressions that set the options for a message and all its inner +// types (nested messages, nested enums, extensions, fields). +void Generator::FixOptionsForMessage(const Descriptor& descriptor) const { + // Nested messages. + for (int i = 0; i < descriptor.nested_type_count(); ++i) { + FixOptionsForMessage(*descriptor.nested_type(i)); + } + // Enums. + for (int i = 0; i < descriptor.enum_type_count(); ++i) { + FixOptionsForEnum(*descriptor.enum_type(i)); + } + // Fields. + for (int i = 0; i < descriptor.field_count(); ++i) { + const FieldDescriptor& field = *descriptor.field(i); + FixOptionsForField(field); + } + // Extensions. + for (int i = 0; i < descriptor.extension_count(); ++i) { + const FieldDescriptor& field = *descriptor.extension(i); + FixOptionsForField(field); + } + // Message option for this message. + string message_options = OptionsValue( + "MessageOptions", descriptor.options().SerializeAsString()); + if (message_options != "None") { + string descriptor_name = ModuleLevelDescriptorName(descriptor); + PrintDescriptorOptionsFixingCode(descriptor_name, + message_options, + printer_); + } +} + } // namespace python } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h index 43c2087..40dfddf 100644 --- a/src/google/protobuf/compiler/python/python_generator.h +++ b/src/google/protobuf/compiler/python/python_generator.h @@ -66,7 +66,7 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { // CodeGenerator methods. virtual bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* generator_context, string* error) const; private: @@ -94,8 +94,11 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void PrintNestedDescriptors(const Descriptor& containing_descriptor) const; void PrintMessages() const; - void PrintMessage(const Descriptor& message_descriptor) const; - void PrintNestedMessages(const Descriptor& containing_descriptor) const; + void PrintMessage(const Descriptor& message_descriptor, const string& prefix, + vector* to_register) const; + void PrintNestedMessages(const Descriptor& containing_descriptor, + const string& prefix, + vector* to_register) const; void FixForeignFieldsInDescriptors() const; void FixForeignFieldsInDescriptor( @@ -104,6 +107,9 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void FixForeignFieldsInField(const Descriptor* containing_type, const FieldDescriptor& field, const string& python_dict_name) const; + void AddMessageToFileDescriptor(const Descriptor& descriptor) const; + void AddEnumToFileDescriptor(const EnumDescriptor& descriptor) const; + void AddExtensionToFileDescriptor(const FieldDescriptor& descriptor) const; string FieldReferencingExpression(const Descriptor* containing_type, const FieldDescriptor& field, const string& python_dict_name) const; @@ -137,6 +143,11 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void PrintSerializedPbInterval( const DescriptorT& descriptor, DescriptorProtoT& proto) const; + void FixAllDescriptorOptions() const; + void FixOptionsForField(const FieldDescriptor& field) const; + void FixOptionsForEnum(const EnumDescriptor& descriptor) const; + void FixOptionsForMessage(const Descriptor& descriptor) const; + // Very coarse-grained lock to ensure that Generate() is reentrant. // Guards file_, printer_ and file_descriptor_serialized_. mutable Mutex mutex_; diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc index fde8876..77da8a8 100644 --- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc +++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc @@ -34,6 +34,8 @@ // It seemed like parameterizing it would add more complexity than it is // worth. +#include + #include #include #include @@ -56,19 +58,19 @@ class TestGenerator : public CodeGenerator { virtual bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { - TryInsert("test_pb2.py", "imports", output_directory); - TryInsert("test_pb2.py", "module_scope", output_directory); - TryInsert("test_pb2.py", "class_scope:foo.Bar", output_directory); - TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", output_directory); + TryInsert("test_pb2.py", "imports", context); + TryInsert("test_pb2.py", "module_scope", context); + TryInsert("test_pb2.py", "class_scope:foo.Bar", context); + TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", context); return true; } void TryInsert(const string& filename, const string& insertion_point, - OutputDirectory* output_directory) const { + GeneratorContext* context) const { scoped_ptr output( - output_directory->OpenForInsert(filename, insertion_point)); + context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } @@ -78,13 +80,13 @@ class TestGenerator : public CodeGenerator { // not verify that they are correctly-placed; that would require actually // compiling the output which is a bit more than I care to do for this test. TEST(PythonPluginTest, PluginTest) { - File::WriteStringToFileOrDie( - "syntax = \"proto2\";\n" - "package foo;\n" - "message Bar {\n" - " message Baz {}\n" - "}\n", - TestTempDir() + "/test.proto"); + GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto", + "syntax = \"proto2\";\n" + "package foo;\n" + "message Bar {\n" + " message Baz {}\n" + "}\n", + true)); google::protobuf::compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index de46a3e..ca4b874 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -32,13 +32,16 @@ #include +#include +#include + #ifndef _WIN32 #include +#include #include #include #endif -#include #include #include #include @@ -96,7 +99,7 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { } // Setup STARTUPINFO to redirect handles. - STARTUPINFO startup_info; + STARTUPINFOA startup_info; ZeroMemory(&startup_info, sizeof(startup_info)); startup_info.cb = sizeof(startup_info); startup_info.dwFlags = STARTF_USESTDHANDLES; @@ -115,16 +118,16 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { // Create the process. PROCESS_INFORMATION process_info; - if (CreateProcess((search_mode == SEARCH_PATH) ? NULL : program.c_str(), - (search_mode == SEARCH_PATH) ? name_copy : NULL, - NULL, // process security attributes - NULL, // thread security attributes - TRUE, // inherit handles? - 0, // obscure creation flags - NULL, // environment (inherit from parent) - NULL, // current directory (inherit from parent) - &startup_info, - &process_info)) { + if (CreateProcessA((search_mode == SEARCH_PATH) ? NULL : program.c_str(), + (search_mode == SEARCH_PATH) ? name_copy : NULL, + NULL, // process security attributes + NULL, // thread security attributes + TRUE, // inherit handles? + 0, // obscure creation flags + NULL, // environment (inherit from parent) + NULL, // current directory (inherit from parent) + &startup_info, + &process_info)) { child_handle_ = process_info.hProcess; CloseHandleOrDie(process_info.hThread); child_stdin_ = stdin_pipe_write; @@ -292,8 +295,8 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { int stdin_pipe[2]; int stdout_pipe[2]; - pipe(stdin_pipe); - pipe(stdout_pipe); + GOOGLE_CHECK(pipe(stdin_pipe) != -1); + GOOGLE_CHECK(pipe(stdout_pipe) != -1); char* argv[2] = { strdup(program.c_str()), NULL }; @@ -321,9 +324,11 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { // Write directly to STDERR_FILENO to avoid stdio code paths that may do // stuff that is unsafe here. - write(STDERR_FILENO, argv[0], strlen(argv[0])); + int ignored; + ignored = write(STDERR_FILENO, argv[0], strlen(argv[0])); const char* message = ": program not found or is not executable\n"; - write(STDERR_FILENO, message, strlen(message)); + ignored = write(STDERR_FILENO, message, strlen(message)); + (void) ignored; // Must use _exit() rather than exit() to avoid flushing output buffers // that will also be flushed by the parent. @@ -444,7 +449,7 @@ bool Subprocess::Communicate(const Message& input, Message* output, } if (!output->ParseFromString(output_data)) { - *error = "Plugin output is unparseable."; + *error = "Plugin output is unparseable: " + CEscape(output_data); return false; } diff --git a/src/google/protobuf/compiler/subprocess.h b/src/google/protobuf/compiler/subprocess.h index 7a6fa70..0056496 100644 --- a/src/google/protobuf/compiler/subprocess.h +++ b/src/google/protobuf/compiler/subprocess.h @@ -40,9 +40,10 @@ #include #include #endif // !_WIN32 +#include #include -#include + namespace google { namespace protobuf { @@ -52,7 +53,7 @@ class Message; namespace compiler { // Utility class for launching sub-processes. -class Subprocess { +class LIBPROTOC_EXPORT Subprocess { public: Subprocess(); ~Subprocess(); diff --git a/src/google/protobuf/compiler/zip_output_unittest.sh b/src/google/protobuf/compiler/zip_output_unittest.sh index 259d5d2..3a02436 100755 --- a/src/google/protobuf/compiler/zip_output_unittest.sh +++ b/src/google/protobuf/compiler/zip_output_unittest.sh @@ -39,45 +39,51 @@ fail() { exit 1 } +TEST_TMPDIR=. +PROTOC=./protoc + echo ' + syntax = "proto2"; option java_multiple_files = true; option java_package = "test.jar"; option java_outer_classname = "Outer"; message Foo {} message Bar {} -' > testzip.proto +' > $TEST_TMPDIR/testzip.proto -./protoc --cpp_out=testzip.zip --python_out=testzip.zip --java_out=testzip.jar \ - testzip.proto || fail 'protoc failed.' +$PROTOC \ + --cpp_out=$TEST_TMPDIR/testzip.zip --python_out=$TEST_TMPDIR/testzip.zip \ + --java_out=$TEST_TMPDIR/testzip.jar -I$TEST_TMPDIR testzip.proto \ + || fail 'protoc failed.' echo "Testing output to zip..." if unzip -h > /dev/null; then - unzip -t testzip.zip > testzip.list || fail 'unzip failed.' + unzip -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list || fail 'unzip failed.' - grep 'testing: testzip\.pb\.cc *OK$' testzip.list > /dev/null \ + grep 'testing: testzip\.pb\.cc *OK$' $TEST_TMPDIR/testzip.list > /dev/null \ || fail 'testzip.pb.cc not found in output zip.' - grep 'testing: testzip\.pb\.h *OK$' testzip.list > /dev/null \ + grep 'testing: testzip\.pb\.h *OK$' $TEST_TMPDIR/testzip.list > /dev/null \ || fail 'testzip.pb.h not found in output zip.' - grep 'testing: testzip_pb2\.py *OK$' testzip.list > /dev/null \ + grep 'testing: testzip_pb2\.py *OK$' $TEST_TMPDIR/testzip.list > /dev/null \ || fail 'testzip_pb2.py not found in output zip.' - grep -i 'manifest' testzip.list > /dev/null \ + grep -i 'manifest' $TEST_TMPDIR/testzip.list > /dev/null \ && fail 'Zip file contained manifest.' else echo "Warning: 'unzip' command not available. Skipping test." fi echo "Testing output to jar..." -if jar c testzip.proto > /dev/null; then - jar tf testzip.jar > testzip.list || fail 'jar failed.' +if jar c $TEST_TMPDIR/testzip.proto > /dev/null; then + jar tf $TEST_TMPDIR/testzip.jar > $TEST_TMPDIR/testzip.list || fail 'jar failed.' - grep '^test/jar/Foo\.java$' testzip.list > /dev/null \ + grep '^test/jar/Foo\.java$' $TEST_TMPDIR/testzip.list > /dev/null \ || fail 'Foo.java not found in output jar.' - grep '^test/jar/Bar\.java$' testzip.list > /dev/null \ + grep '^test/jar/Bar\.java$' $TEST_TMPDIR/testzip.list > /dev/null \ || fail 'Bar.java not found in output jar.' - grep '^test/jar/Outer\.java$' testzip.list > /dev/null \ + grep '^test/jar/Outer\.java$' $TEST_TMPDIR/testzip.list > /dev/null \ || fail 'Outer.java not found in output jar.' - grep '^META-INF/MANIFEST\.MF$' testzip.list > /dev/null \ - || fail 'Manifest not ofund in output jar.' + grep '^META-INF/MANIFEST\.MF$' $TEST_TMPDIR/testzip.list > /dev/null \ + || fail 'Manifest not found in output jar.' else echo "Warning: 'jar' command not available. Skipping test." fi diff --git a/src/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc index 53c1877..65d7352 100644 --- a/src/google/protobuf/compiler/zip_writer.cc +++ b/src/google/protobuf/compiler/zip_writer.cc @@ -28,6 +28,36 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + // Author: ambrose@google.com (Ambrose Feinstein), // kenton@google.com (Kenton Varda) // @@ -183,6 +213,6 @@ bool ZipWriter::WriteDirectory() { return output.HadError(); } -} // namespace google -} // namespace protobuf } // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h index 4289553..be73972 100644 --- a/src/google/protobuf/compiler/zip_writer.h +++ b/src/google/protobuf/compiler/zip_writer.h @@ -28,6 +28,36 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + // Author: kenton@google.com (Kenton Varda) #include @@ -58,6 +88,6 @@ class ZipWriter { vector files_; }; -} // namespace google -} // namespace protobuf } // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 81c4ac0..17e1cc1 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -42,17 +43,21 @@ #include #include #include +#include +#include #include #include #include +#include #include +#include #include #include #include #include #include -#include -#include +#include +#include #undef PACKAGE // autoheader #defines this. :( @@ -106,6 +111,21 @@ const char * const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = { "sint64", // TYPE_SINT64 }; +const char * const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = { + "ERROR", // 0 is reserved for errors + + "int32", // CPPTYPE_INT32 + "int64", // CPPTYPE_INT64 + "uint32", // CPPTYPE_UINT32 + "uint64", // CPPTYPE_UINT64 + "double", // CPPTYPE_DOUBLE + "float", // CPPTYPE_FLOAT + "bool", // CPPTYPE_BOOL + "enum", // CPPTYPE_ENUM + "string", // CPPTYPE_STRING + "message", // CPPTYPE_MESSAGE +}; + const char * const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = { "ERROR", // 0 is reserved for errors @@ -114,6 +134,8 @@ const char * const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = { "repeated", // LABEL_REPEATED }; +static const char * const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty"; + #ifndef _MSC_VER // MSVC doesn't need these and won't even accept them. const int FieldDescriptor::kMaxNumber; const int FieldDescriptor::kFirstReservedNumber; @@ -122,8 +144,6 @@ const int FieldDescriptor::kLastReservedNumber; namespace { -const string kEmptyString; - string ToCamelCase(const string& input) { bool capitalize_next = false; string result; @@ -184,9 +204,11 @@ struct PointerIntegerPairHash { return reinterpret_cast(p.first) * ((1 << 16) - 1) + p.second; } +#ifdef _MSC_VER // Used only by MSVC and platforms where hash_map is not available. static const size_t bucket_size = 4; static const size_t min_buckets = 8; +#endif inline bool operator()(const PairType& a, const PairType& b) const { return a.first < b.first || (a.first == b.first && a.second < b.second); @@ -205,9 +227,11 @@ struct PointerStringPairHash { cstring_hash(p.second); } +#ifdef _MSC_VER // Used only by MSVC and platforms where hash_map is not available. static const size_t bucket_size = 4; static const size_t min_buckets = 8; +#endif inline bool operator()(const PointerStringPair& a, const PointerStringPair& b) const { if (a.first < b.first) return true; @@ -219,12 +243,14 @@ struct PointerStringPairHash { struct Symbol { enum Type { - NULL_SYMBOL, MESSAGE, FIELD, ENUM, ENUM_VALUE, SERVICE, METHOD, PACKAGE + NULL_SYMBOL, MESSAGE, FIELD, ONEOF, ENUM, ENUM_VALUE, SERVICE, METHOD, + PACKAGE }; Type type; union { const Descriptor* descriptor; const FieldDescriptor* field_descriptor; + const OneofDescriptor* oneof_descriptor; const EnumDescriptor* enum_descriptor; const EnumValueDescriptor* enum_value_descriptor; const ServiceDescriptor* service_descriptor; @@ -250,6 +276,7 @@ struct Symbol { CONSTRUCTOR(Descriptor , MESSAGE , descriptor ) CONSTRUCTOR(FieldDescriptor , FIELD , field_descriptor ) + CONSTRUCTOR(OneofDescriptor , ONEOF , oneof_descriptor ) CONSTRUCTOR(EnumDescriptor , ENUM , enum_descriptor ) CONSTRUCTOR(EnumValueDescriptor, ENUM_VALUE, enum_value_descriptor ) CONSTRUCTOR(ServiceDescriptor , SERVICE , service_descriptor ) @@ -262,6 +289,7 @@ struct Symbol { case NULL_SYMBOL: return NULL; case MESSAGE : return descriptor ->file(); case FIELD : return field_descriptor ->file(); + case ONEOF : return oneof_descriptor ->containing_type()->file(); case ENUM : return enum_descriptor ->file(); case ENUM_VALUE : return enum_value_descriptor->type()->file(); case SERVICE : return service_descriptor ->file(); @@ -298,7 +326,7 @@ typedef hash_map ExtensionsGroupedByDescriptorMap; - +typedef hash_map LocationsByPathMap; } // anonymous namespace // =================================================================== @@ -309,17 +337,42 @@ class DescriptorPool::Tables { Tables(); ~Tables(); - // Checkpoint the state of the tables. Future calls to Rollback() will - // return the Tables to this state. This is used when building files, since - // some kinds of validation errors cannot be detected until the file's - // descriptors have already been added to the tables. BuildFile() calls - // Checkpoint() before it starts building and Rollback() if it encounters - // an error. - void Checkpoint(); + // Record the current state of the tables to the stack of checkpoints. + // Each call to AddCheckpoint() must be paired with exactly one call to either + // ClearLastCheckpoint() or RollbackToLastCheckpoint(). + // + // This is used when building files, since some kinds of validation errors + // cannot be detected until the file's descriptors have already been added to + // the tables. + // + // This supports recursive checkpoints, since building a file may trigger + // recursive building of other files. Note that recursive checkpoints are not + // normally necessary; explicit dependencies are built prior to checkpointing. + // So although we recursively build transitive imports, there is at most one + // checkpoint in the stack during dependency building. + // + // Recursive checkpoints only arise during cross-linking of the descriptors. + // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and + // friends. If the pending file references an unknown symbol + // (e.g., it is not defined in the pending file's explicit dependencies), and + // the pool is using a fallback database, and that database contains a file + // defining that symbol, and that file has not yet been built by the pool, + // the pool builds the file during cross-linking, leading to another + // checkpoint. + void AddCheckpoint(); + + // Mark the last checkpoint as having cleared successfully, removing it from + // the stack. If the stack is empty, all pending symbols will be committed. + // + // Note that this does not guarantee that the symbols added since the last + // checkpoint won't be rolled back: if a checkpoint gets rolled back, + // everything past that point gets rolled back, including symbols added after + // checkpoints that were pushed onto the stack after it and marked as cleared. + void ClearLastCheckpoint(); - // Roll back the Tables to the state of the last Checkpoint(), removing - // everything that was added after that point. - void Rollback(); + // Roll back the Tables to the state of the checkpoint at the top of the + // stack, removing everything that was added after that point. + void RollbackToLastCheckpoint(); // The stack of files which are currently being built. Used to detect // cyclic dependencies when loading files from a DescriptorDatabase. Not @@ -327,10 +380,18 @@ class DescriptorPool::Tables { vector pending_files_; // A set of files which we have tried to load from the fallback database - // and encountered errors. We will not attempt to load them again. + // and encountered errors. We will not attempt to load them again during + // execution of the current public API call, but for compatibility with + // legacy clients, this is cleared at the beginning of each public API call. // Not used when fallback_database_ == NULL. hash_set known_bad_files_; + // A set of symbols which we have tried to load from the fallback database + // and encountered errors. We will not attempt to load them again during + // execution of the current public API call, but for compatibility with + // legacy clients, this is cleared at the beginning of each public API call. + hash_set known_bad_symbols_; + // The set of descriptors for which we've already loaded the full // set of extensions numbers from fallback_database_. hash_set extensions_loaded_from_db_; @@ -347,7 +408,7 @@ class DescriptorPool::Tables { // declaring Symbol in descriptor.h, which would drag all kinds of other // stuff into the header. Yay C++. Symbol FindByNameHelper( - const DescriptorPool* pool, const string& name) const; + const DescriptorPool* pool, const string& name); // These return NULL if not found. inline const FileDescriptor* FindFile(const string& key) const; @@ -403,10 +464,28 @@ class DescriptorPool::Tables { FilesByNameMap files_by_name_; ExtensionsGroupedByDescriptorMap extensions_; - int strings_before_checkpoint_; - int messages_before_checkpoint_; - int file_tables_before_checkpoint_; - int allocations_before_checkpoint_; + struct CheckPoint { + explicit CheckPoint(const Tables* tables) + : strings_before_checkpoint(tables->strings_.size()), + messages_before_checkpoint(tables->messages_.size()), + file_tables_before_checkpoint(tables->file_tables_.size()), + allocations_before_checkpoint(tables->allocations_.size()), + pending_symbols_before_checkpoint( + tables->symbols_after_checkpoint_.size()), + pending_files_before_checkpoint( + tables->files_after_checkpoint_.size()), + pending_extensions_before_checkpoint( + tables->extensions_after_checkpoint_.size()) { + } + int strings_before_checkpoint; + int messages_before_checkpoint; + int file_tables_before_checkpoint; + int allocations_before_checkpoint; + int pending_symbols_before_checkpoint; + int pending_files_before_checkpoint; + int pending_extensions_before_checkpoint; + }; + vector checkpoints_; vector symbols_after_checkpoint_; vector files_after_checkpoint_; vector extensions_after_checkpoint_; @@ -470,20 +549,41 @@ class FileDescriptorTables { // fails because we allow duplicates; the first field by the name wins. void AddFieldByStylizedNames(const FieldDescriptor* field); + // Populates p->first->locations_by_path_ from p->second. + // Unusual signature dictated by GoogleOnceDynamic. + static void BuildLocationsByPath( + pair* p); + + // Returns the location denoted by the specified path through info, + // or NULL if not found. + // The value of info must be that of the corresponding FileDescriptor. + // (Conceptually a pure function, but stateful as an optimisation.) + const SourceCodeInfo_Location* GetSourceLocation( + const vector& path, const SourceCodeInfo* info) const; + private: SymbolsByParentMap symbols_by_parent_; FieldsByNameMap fields_by_lowercase_name_; FieldsByNameMap fields_by_camelcase_name_; FieldsByNumberMap fields_by_number_; // Not including extensions. EnumValuesByNumberMap enum_values_by_number_; + + // Populated on first request to save space, hence constness games. + mutable GoogleOnceDynamic locations_by_path_once_; + mutable LocationsByPathMap locations_by_path_; }; DescriptorPool::Tables::Tables() - : strings_before_checkpoint_(0), - messages_before_checkpoint_(0), - allocations_before_checkpoint_(0) {} + // Start some hash_map and hash_set objects with a small # of buckets + : known_bad_files_(3), + known_bad_symbols_(3), + extensions_loaded_from_db_(3), + symbols_by_name_(3), + files_by_name_(3) {} + DescriptorPool::Tables::~Tables() { + GOOGLE_DCHECK(checkpoints_.empty()); // Note that the deletion order is important, since the destructors of some // messages may refer to objects in allocations_. STLDeleteElements(&messages_); @@ -494,51 +594,80 @@ DescriptorPool::Tables::~Tables() { STLDeleteElements(&file_tables_); } -FileDescriptorTables::FileDescriptorTables() {} +FileDescriptorTables::FileDescriptorTables() + // Initialize all the hash tables to start out with a small # of buckets + : symbols_by_parent_(3), + fields_by_lowercase_name_(3), + fields_by_camelcase_name_(3), + fields_by_number_(3), + enum_values_by_number_(3) { +} + FileDescriptorTables::~FileDescriptorTables() {} const FileDescriptorTables FileDescriptorTables::kEmpty; -void DescriptorPool::Tables::Checkpoint() { - strings_before_checkpoint_ = strings_.size(); - messages_before_checkpoint_ = messages_.size(); - file_tables_before_checkpoint_ = file_tables_.size(); - allocations_before_checkpoint_ = allocations_.size(); +void DescriptorPool::Tables::AddCheckpoint() { + checkpoints_.push_back(CheckPoint(this)); +} - symbols_after_checkpoint_.clear(); - files_after_checkpoint_.clear(); - extensions_after_checkpoint_.clear(); +void DescriptorPool::Tables::ClearLastCheckpoint() { + GOOGLE_DCHECK(!checkpoints_.empty()); + checkpoints_.pop_back(); + if (checkpoints_.empty()) { + // All checkpoints have been cleared: we can now commit all of the pending + // data. + symbols_after_checkpoint_.clear(); + files_after_checkpoint_.clear(); + extensions_after_checkpoint_.clear(); + } } -void DescriptorPool::Tables::Rollback() { - for (int i = 0; i < symbols_after_checkpoint_.size(); i++) { +void DescriptorPool::Tables::RollbackToLastCheckpoint() { + GOOGLE_DCHECK(!checkpoints_.empty()); + const CheckPoint& checkpoint = checkpoints_.back(); + + for (int i = checkpoint.pending_symbols_before_checkpoint; + i < symbols_after_checkpoint_.size(); + i++) { symbols_by_name_.erase(symbols_after_checkpoint_[i]); } - for (int i = 0; i < files_after_checkpoint_.size(); i++) { + for (int i = checkpoint.pending_files_before_checkpoint; + i < files_after_checkpoint_.size(); + i++) { files_by_name_.erase(files_after_checkpoint_[i]); } - for (int i = 0; i < extensions_after_checkpoint_.size(); i++) { + for (int i = checkpoint.pending_extensions_before_checkpoint; + i < extensions_after_checkpoint_.size(); + i++) { extensions_.erase(extensions_after_checkpoint_[i]); } - symbols_after_checkpoint_.clear(); - files_after_checkpoint_.clear(); - extensions_after_checkpoint_.clear(); + symbols_after_checkpoint_.resize( + checkpoint.pending_symbols_before_checkpoint); + files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint); + extensions_after_checkpoint_.resize( + checkpoint.pending_extensions_before_checkpoint); STLDeleteContainerPointers( - strings_.begin() + strings_before_checkpoint_, strings_.end()); + strings_.begin() + checkpoint.strings_before_checkpoint, strings_.end()); STLDeleteContainerPointers( - messages_.begin() + messages_before_checkpoint_, messages_.end()); + messages_.begin() + checkpoint.messages_before_checkpoint, + messages_.end()); STLDeleteContainerPointers( - file_tables_.begin() + file_tables_before_checkpoint_, file_tables_.end()); - for (int i = allocations_before_checkpoint_; i < allocations_.size(); i++) { + file_tables_.begin() + checkpoint.file_tables_before_checkpoint, + file_tables_.end()); + for (int i = checkpoint.allocations_before_checkpoint; + i < allocations_.size(); + i++) { operator delete(allocations_[i]); } - strings_.resize(strings_before_checkpoint_); - messages_.resize(messages_before_checkpoint_); - file_tables_.resize(file_tables_before_checkpoint_); - allocations_.resize(allocations_before_checkpoint_); + strings_.resize(checkpoint.strings_before_checkpoint); + messages_.resize(checkpoint.messages_before_checkpoint); + file_tables_.resize(checkpoint.file_tables_before_checkpoint); + allocations_.resize(checkpoint.allocations_before_checkpoint); + checkpoints_.pop_back(); } // ------------------------------------------------------------------- @@ -571,8 +700,10 @@ inline Symbol FileDescriptorTables::FindNestedSymbolOfType( } Symbol DescriptorPool::Tables::FindByNameHelper( - const DescriptorPool* pool, const string& name) const { + const DescriptorPool* pool, const string& name) { MutexLockMaybe lock(pool->mutex_); + known_bad_symbols_.clear(); + known_bad_files_.clear(); Symbol result = FindSymbol(name); if (result.IsNull() && pool->underlay_ != NULL) { @@ -719,7 +850,7 @@ string* DescriptorPool::Tables::AllocateString(const string& value) { } template -Type* DescriptorPool::Tables::AllocateMessage(Type* dummy) { +Type* DescriptorPool::Tables::AllocateMessage(Type* /* dummy */) { Type* result = new Type; messages_.push_back(result); return result; @@ -743,6 +874,22 @@ void* DescriptorPool::Tables::AllocateBytes(int size) { return result; } +void FileDescriptorTables::BuildLocationsByPath( + pair* p) { + for (int i = 0, len = p->second->location_size(); i < len; ++i) { + const SourceCodeInfo_Location* loc = &p->second->location().Get(i); + p->first->locations_by_path_[Join(loc->path(), ",")] = loc; + } +} + +const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation( + const vector& path, const SourceCodeInfo* info) const { + pair p( + make_pair(this, info)); + locations_by_path_once_.Init(&FileDescriptorTables::BuildLocationsByPath, &p); + return FindPtrOrNull(locations_by_path_, Join(path, ",")); +} + // =================================================================== // DescriptorPool @@ -755,7 +902,8 @@ DescriptorPool::DescriptorPool() underlay_(NULL), tables_(new Tables), enforce_dependencies_(true), - allow_unknown_(false) {} + allow_unknown_(false), + enforce_weak_(false) {} DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database, ErrorCollector* error_collector) @@ -765,7 +913,8 @@ DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database, underlay_(NULL), tables_(new Tables), enforce_dependencies_(true), - allow_unknown_(false) { + allow_unknown_(false), + enforce_weak_(false) { } DescriptorPool::DescriptorPool(const DescriptorPool* underlay) @@ -775,7 +924,8 @@ DescriptorPool::DescriptorPool(const DescriptorPool* underlay) underlay_(underlay), tables_(new Tables), enforce_dependencies_(true), - allow_unknown_(false) {} + allow_unknown_(false), + enforce_weak_(false) {} DescriptorPool::~DescriptorPool() { if (mutex_ != NULL) delete mutex_; @@ -788,6 +938,14 @@ void DescriptorPool::InternalDontEnforceDependencies() { enforce_dependencies_ = false; } +void DescriptorPool::AddUnusedImportTrackFile(const string& file_name) { + unused_import_track_files_.insert(file_name); +} + +void DescriptorPool::ClearUnusedImportTrackFiles() { + unused_import_track_files_.clear(); +} + bool DescriptorPool::InternalIsFileLoaded(const string& filename) const { MutexLockMaybe lock(mutex_); return tables_->FindFile(filename) != NULL; @@ -809,7 +967,7 @@ void DeleteGeneratedPool() { generated_pool_ = NULL; } -void InitGeneratedPool() { +static void InitGeneratedPool() { generated_database_ = new EncodedDescriptorDatabase; generated_pool_ = new DescriptorPool(generated_database_); @@ -869,14 +1027,16 @@ void DescriptorPool::InternalAddGeneratedFile( const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const { MutexLockMaybe lock(mutex_); + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); const FileDescriptor* result = tables_->FindFile(name); if (result != NULL) return result; if (underlay_ != NULL) { - const FileDescriptor* result = underlay_->FindFileByName(name); + result = underlay_->FindFileByName(name); if (result != NULL) return result; } if (TryFindFileInFallbackDatabase(name)) { - const FileDescriptor* result = tables_->FindFile(name); + result = tables_->FindFile(name); if (result != NULL) return result; } return NULL; @@ -885,15 +1045,17 @@ const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const { const FileDescriptor* DescriptorPool::FindFileContainingSymbol( const string& symbol_name) const { MutexLockMaybe lock(mutex_); + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); Symbol result = tables_->FindSymbol(symbol_name); if (!result.IsNull()) return result.GetFile(); if (underlay_ != NULL) { - const FileDescriptor* result = + const FileDescriptor* file_result = underlay_->FindFileContainingSymbol(symbol_name); - if (result != NULL) return result; + if (file_result != NULL) return file_result; } if (TryFindSymbolInFallbackDatabase(symbol_name)) { - Symbol result = tables_->FindSymbol(symbol_name); + result = tables_->FindSymbol(symbol_name); if (!result.IsNull()) return result.GetFile(); } return NULL; @@ -927,6 +1089,12 @@ const FieldDescriptor* DescriptorPool::FindExtensionByName( } } +const OneofDescriptor* DescriptorPool::FindOneofByName( + const string& name) const { + Symbol result = tables_->FindByNameHelper(this, name); + return (result.type == Symbol::ONEOF) ? result.oneof_descriptor : NULL; +} + const EnumDescriptor* DescriptorPool::FindEnumTypeByName( const string& name) const { Symbol result = tables_->FindByNameHelper(this, name); @@ -955,17 +1123,18 @@ const MethodDescriptor* DescriptorPool::FindMethodByName( const FieldDescriptor* DescriptorPool::FindExtensionByNumber( const Descriptor* extendee, int number) const { MutexLockMaybe lock(mutex_); + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); const FieldDescriptor* result = tables_->FindExtension(extendee, number); if (result != NULL) { return result; } if (underlay_ != NULL) { - const FieldDescriptor* result = - underlay_->FindExtensionByNumber(extendee, number); + result = underlay_->FindExtensionByNumber(extendee, number); if (result != NULL) return result; } if (TryFindExtensionInFallbackDatabase(extendee, number)) { - const FieldDescriptor* result = tables_->FindExtension(extendee, number); + result = tables_->FindExtension(extendee, number); if (result != NULL) { return result; } @@ -976,6 +1145,8 @@ const FieldDescriptor* DescriptorPool::FindExtensionByNumber( void DescriptorPool::FindAllExtensions( const Descriptor* extendee, vector* out) const { MutexLockMaybe lock(mutex_); + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); // Initialize tables_->extensions_ from the fallback database first // (but do this only once per descriptor). @@ -1000,6 +1171,7 @@ void DescriptorPool::FindAllExtensions( } } + // ------------------------------------------------------------------- const FieldDescriptor* @@ -1046,6 +1218,17 @@ Descriptor::FindFieldByName(const string& key) const { } } +const OneofDescriptor* +Descriptor::FindOneofByName(const string& key) const { + Symbol result = + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ONEOF); + if (!result.IsNull()) { + return result.oneof_descriptor; + } else { + return NULL; + } +} + const FieldDescriptor* Descriptor::FindExtensionByName(const string& key) const { Symbol result = @@ -1210,16 +1393,17 @@ FileDescriptor::FindExtensionByCamelcaseName(const string& key) const { } } -bool Descriptor::IsExtensionNumber(int number) const { +const Descriptor::ExtensionRange* +Descriptor::FindExtensionRangeContainingNumber(int number) const { // Linear search should be fine because we don't expect a message to have // more than a couple extension ranges. for (int i = 0; i < extension_range_count(); i++) { if (number >= extension_range(i)->start && number < extension_range(i)->end) { - return true; + return extension_range(i); } } - return false; + return NULL; } // ------------------------------------------------------------------- @@ -1235,26 +1419,66 @@ bool DescriptorPool::TryFindFileInFallbackDatabase(const string& name) const { tables_->known_bad_files_.insert(name); return false; } - return true; } +bool DescriptorPool::IsSubSymbolOfBuiltType(const string& name) const { + string prefix = name; + for (;;) { + string::size_type dot_pos = prefix.find_last_of('.'); + if (dot_pos == string::npos) { + break; + } + prefix = prefix.substr(0, dot_pos); + Symbol symbol = tables_->FindSymbol(prefix); + // If the symbol type is anything other than PACKAGE, then its complete + // definition is already known. + if (!symbol.IsNull() && symbol.type != Symbol::PACKAGE) { + return true; + } + } + if (underlay_ != NULL) { + // Check to see if any prefix of this symbol exists in the underlay. + return underlay_->IsSubSymbolOfBuiltType(name); + } + return false; +} + bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const { if (fallback_database_ == NULL) return false; - FileDescriptorProto file_proto; - if (!fallback_database_->FindFileContainingSymbol(name, &file_proto)) { - return false; - } - - if (tables_->FindFile(file_proto.name()) != NULL) { - // We've already loaded this file, and it apparently doesn't contain the - // symbol we're looking for. Some DescriptorDatabases return false - // positives. - return false; - } + if (tables_->known_bad_symbols_.count(name) > 0) return false; - if (BuildFileFromDatabase(file_proto) == NULL) { + FileDescriptorProto file_proto; + if (// We skip looking in the fallback database if the name is a sub-symbol + // of any descriptor that already exists in the descriptor pool (except + // for package descriptors). This is valid because all symbols except + // for packages are defined in a single file, so if the symbol exists + // then we should already have its definition. + // + // The other reason to do this is to support "overriding" type + // definitions by merging two databases that define the same type. (Yes, + // people do this.) The main difficulty with making this work is that + // FindFileContainingSymbol() is allowed to return both false positives + // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and false + // negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase). + // When two such databases are merged, looking up a non-existent + // sub-symbol of a type that already exists in the descriptor pool can + // result in an attempt to load multiple definitions of the same type. + // The check below avoids this. + IsSubSymbolOfBuiltType(name) + + // Look up file containing this symbol in fallback database. + || !fallback_database_->FindFileContainingSymbol(name, &file_proto) + + // Check if we've already built this file. If so, it apparently doesn't + // contain the symbol we're looking for. Some DescriptorDatabases + // return false positives. + || tables_->FindFile(file_proto.name()) != NULL + + // Build the file. + || BuildFileFromDatabase(file_proto) == NULL) { + tables_->known_bad_symbols_.insert(name); return false; } @@ -1343,6 +1567,14 @@ void FileDescriptor::CopyTo(FileDescriptorProto* proto) const { proto->add_dependency(dependency(i)->name()); } + for (int i = 0; i < public_dependency_count(); i++) { + proto->add_public_dependency(public_dependencies_[i]); + } + + for (int i = 0; i < weak_dependency_count(); i++) { + proto->add_weak_dependency(weak_dependencies_[i]); + } + for (int i = 0; i < message_type_count(); i++) { message_type(i)->CopyTo(proto->add_message_type()); } @@ -1361,12 +1593,21 @@ void FileDescriptor::CopyTo(FileDescriptorProto* proto) const { } } +void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const { + if (source_code_info_ != &SourceCodeInfo::default_instance()) { + proto->mutable_source_code_info()->CopyFrom(*source_code_info_); + } +} + void Descriptor::CopyTo(DescriptorProto* proto) const { proto->set_name(name()); for (int i = 0; i < field_count(); i++) { field(i)->CopyTo(proto->add_field()); } + for (int i = 0; i < oneof_decl_count(); i++) { + oneof_decl(i)->CopyTo(proto->add_oneof_decl()); + } for (int i = 0; i < nested_type_count(); i++) { nested_type(i)->CopyTo(proto->add_nested_type()); } @@ -1427,11 +1668,19 @@ void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const { proto->set_default_value(DefaultValueAsString(false)); } + if (containing_oneof() != NULL && !is_extension()) { + proto->set_oneof_index(containing_oneof()->index()); + } + if (&options() != &FieldOptions::default_instance()) { proto->mutable_options()->CopyFrom(options()); } } +void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const { + proto->set_name(name()); +} + void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const { proto->set_name(name()); @@ -1488,16 +1737,14 @@ void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const { namespace { // Used by each of the option formatters. -bool RetrieveOptions(const Message &options, vector *option_entries) { +bool RetrieveOptions(int depth, + const Message &options, + vector *option_entries) { option_entries->clear(); const Reflection* reflection = options.GetReflection(); vector fields; reflection->ListFields(options, &fields); for (int i = 0; i < fields.size(); i++) { - // Doesn't make sense to have message type fields here - if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - continue; - } int count = 1; bool repeated = false; if (fields[i]->is_repeated()) { @@ -1506,9 +1753,27 @@ bool RetrieveOptions(const Message &options, vector *option_entries) { } for (int j = 0; j < count; j++) { string fieldval; - TextFormat::PrintFieldValueToString(options, fields[i], - repeated ? count : -1, &fieldval); - option_entries->push_back(fields[i]->name() + " = " + fieldval); + if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + string tmp; + TextFormat::Printer printer; + printer.SetInitialIndentLevel(depth + 1); + printer.PrintFieldValueToString(options, fields[i], + repeated ? j : -1, &tmp); + fieldval.append("{\n"); + fieldval.append(tmp); + fieldval.append(depth * 2, ' '); + fieldval.append("}"); + } else { + TextFormat::PrintFieldValueToString(options, fields[i], + repeated ? j : -1, &fieldval); + } + string name; + if (fields[i]->is_extension()) { + name = "(." + fields[i]->full_name() + ")"; + } else { + name = fields[i]->name(); + } + option_entries->push_back(name + " = " + fieldval); } } return !option_entries->empty(); @@ -1516,10 +1781,10 @@ bool RetrieveOptions(const Message &options, vector *option_entries) { // Formats options that all appear together in brackets. Does not include // brackets. -bool FormatBracketedOptions(const Message &options, string *output) { +bool FormatBracketedOptions(int depth, const Message &options, string *output) { vector all_options; - if (RetrieveOptions(options, &all_options)) { - output->append(JoinStrings(all_options, ", ")); + if (RetrieveOptions(depth, options, &all_options)) { + output->append(Join(all_options, ", ")); } return !all_options.empty(); } @@ -1528,7 +1793,7 @@ bool FormatBracketedOptions(const Message &options, string *output) { bool FormatLineOptions(int depth, const Message &options, string *output) { string prefix(depth * 2, ' '); vector all_options; - if (RetrieveOptions(options, &all_options)) { + if (RetrieveOptions(depth, options, &all_options)) { for (int i = 0; i < all_options.size(); i++) { strings::SubstituteAndAppend(output, "$0option $1;\n", prefix, all_options[i]); @@ -1542,9 +1807,24 @@ bool FormatLineOptions(int depth, const Message &options, string *output) { string FileDescriptor::DebugString() const { string contents = "syntax = \"proto2\";\n\n"; + set public_dependencies; + set weak_dependencies; + public_dependencies.insert(public_dependencies_, + public_dependencies_ + public_dependency_count_); + weak_dependencies.insert(weak_dependencies_, + weak_dependencies_ + weak_dependency_count_); + for (int i = 0; i < dependency_count(); i++) { - strings::SubstituteAndAppend(&contents, "import \"$0\";\n", - dependency(i)->name()); + if (public_dependencies.count(i) > 0) { + strings::SubstituteAndAppend(&contents, "import public \"$0\";\n", + dependency(i)->name()); + } else if (weak_dependencies.count(i) > 0) { + strings::SubstituteAndAppend(&contents, "import weak \"$0\";\n", + dependency(i)->name()); + } else { + strings::SubstituteAndAppend(&contents, "import \"$0\";\n", + dependency(i)->name()); + } } if (!package().empty()) { @@ -1591,7 +1871,7 @@ string FileDescriptor::DebugString() const { strings::SubstituteAndAppend(&contents, "extend .$0 {\n", containing_type->full_name()); } - extension(i)->DebugString(1, &contents); + extension(i)->DebugString(1, FieldDescriptor::PRINT_LABEL, &contents); } if (extension_count() > 0) contents.append("}\n\n"); @@ -1638,7 +1918,12 @@ void Descriptor::DebugString(int depth, string *contents) const { enum_type(i)->DebugString(depth, contents); } for (int i = 0; i < field_count(); i++) { - field(i)->DebugString(depth, contents); + if (field(i)->containing_oneof() == NULL) { + field(i)->DebugString(depth, FieldDescriptor::PRINT_LABEL, contents); + } else if (field(i)->containing_oneof()->field(0) == field(i)) { + // This is the first field in this oneof, so print the whole oneof. + field(i)->containing_oneof()->DebugString(depth, contents); + } } for (int i = 0; i < extension_range_count(); i++) { @@ -1657,7 +1942,8 @@ void Descriptor::DebugString(int depth, string *contents) const { strings::SubstituteAndAppend(contents, "$0 extend .$1 {\n", prefix, containing_type->full_name()); } - extension(i)->DebugString(depth + 1, contents); + extension(i)->DebugString( + depth + 1, FieldDescriptor::PRINT_LABEL, contents); } if (extension_count() > 0) strings::SubstituteAndAppend(contents, "$0 }\n", prefix); @@ -1673,14 +1959,16 @@ string FieldDescriptor::DebugString() const { containing_type()->full_name()); depth = 1; } - DebugString(depth, &contents); + DebugString(depth, PRINT_LABEL, &contents); if (is_extension()) { - contents.append("}\n"); + contents.append("}\n"); } return contents; } -void FieldDescriptor::DebugString(int depth, string *contents) const { +void FieldDescriptor::DebugString(int depth, + PrintLabelFlag print_label_flag, + string *contents) const { string prefix(depth * 2, ' '); string field_type; switch (type()) { @@ -1694,9 +1982,15 @@ void FieldDescriptor::DebugString(int depth, string *contents) const { field_type = kTypeToName[type()]; } - strings::SubstituteAndAppend(contents, "$0$1 $2 $3 = $4", + string label; + if (print_label_flag == PRINT_LABEL) { + label = kLabelToName[this->label()]; + label.push_back(' '); + } + + strings::SubstituteAndAppend(contents, "$0$1$2 $3 = $4", prefix, - kLabelToName[label()], + label, field_type, type() == TYPE_GROUP ? message_type()->name() : name(), @@ -1710,7 +2004,7 @@ void FieldDescriptor::DebugString(int depth, string *contents) const { } string formatted_options; - if (FormatBracketedOptions(options(), &formatted_options)) { + if (FormatBracketedOptions(depth, options(), &formatted_options)) { contents->append(bracketed ? ", " : " ["); bracketed = true; contents->append(formatted_options); @@ -1727,6 +2021,23 @@ void FieldDescriptor::DebugString(int depth, string *contents) const { } } +string OneofDescriptor::DebugString() const { + string contents; + DebugString(0, &contents); + return contents; +} + +void OneofDescriptor::DebugString(int depth, string* contents) const { + string prefix(depth * 2, ' '); + ++depth; + strings::SubstituteAndAppend( + contents, "$0 oneof $1 {\n", prefix, name()); + for (int i = 0; i < field_count(); i++) { + field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents); + } + strings::SubstituteAndAppend(contents, "$0}\n", prefix); +} + string EnumDescriptor::DebugString() const { string contents; DebugString(0, &contents); @@ -1759,7 +2070,7 @@ void EnumValueDescriptor::DebugString(int depth, string *contents) const { prefix, name(), number()); string formatted_options; - if (FormatBracketedOptions(options(), &formatted_options)) { + if (FormatBracketedOptions(depth, options(), &formatted_options)) { strings::SubstituteAndAppend(contents, " [$0]", formatted_options); } contents->append(";\n"); @@ -1805,6 +2116,141 @@ void MethodDescriptor::DebugString(int depth, string *contents) const { contents->append(";\n"); } } + + +// Location methods =============================================== + +bool FileDescriptor::GetSourceLocation(const vector& path, + SourceLocation* out_location) const { + GOOGLE_CHECK_NOTNULL(out_location); + if (source_code_info_) { + if (const SourceCodeInfo_Location* loc = + tables_->GetSourceLocation(path, source_code_info_)) { + const RepeatedField& span = loc->span(); + if (span.size() == 3 || span.size() == 4) { + out_location->start_line = span.Get(0); + out_location->start_column = span.Get(1); + out_location->end_line = span.Get(span.size() == 3 ? 0 : 2); + out_location->end_column = span.Get(span.size() - 1); + + out_location->leading_comments = loc->leading_comments(); + out_location->trailing_comments = loc->trailing_comments(); + return true; + } + } + } + return false; +} + +bool FieldDescriptor::is_packed() const { + return is_packable() && (options_ != NULL) && options_->packed(); +} + +bool Descriptor::GetSourceLocation(SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return file()->GetSourceLocation(path, out_location); +} + +bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return file()->GetSourceLocation(path, out_location); +} + +bool OneofDescriptor::GetSourceLocation(SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return containing_type()->file()->GetSourceLocation(path, out_location); +} + +bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return file()->GetSourceLocation(path, out_location); +} + +bool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return service()->file()->GetSourceLocation(path, out_location); +} + +bool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return file()->GetSourceLocation(path, out_location); +} + +bool EnumValueDescriptor::GetSourceLocation( + SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return type()->file()->GetSourceLocation(path, out_location); +} + +void Descriptor::GetLocationPath(vector* output) const { + if (containing_type()) { + containing_type()->GetLocationPath(output); + output->push_back(DescriptorProto::kNestedTypeFieldNumber); + output->push_back(index()); + } else { + output->push_back(FileDescriptorProto::kMessageTypeFieldNumber); + output->push_back(index()); + } +} + +void FieldDescriptor::GetLocationPath(vector* output) const { + if (is_extension()) { + if (extension_scope() == NULL) { + output->push_back(FileDescriptorProto::kExtensionFieldNumber); + output->push_back(index()); + } else { + extension_scope()->GetLocationPath(output); + output->push_back(DescriptorProto::kExtensionFieldNumber); + output->push_back(index()); + } + } else { + containing_type()->GetLocationPath(output); + output->push_back(DescriptorProto::kFieldFieldNumber); + output->push_back(index()); + } +} + +void OneofDescriptor::GetLocationPath(vector* output) const { + containing_type()->GetLocationPath(output); + output->push_back(DescriptorProto::kOneofDeclFieldNumber); + output->push_back(index()); +} + +void EnumDescriptor::GetLocationPath(vector* output) const { + if (containing_type()) { + containing_type()->GetLocationPath(output); + output->push_back(DescriptorProto::kEnumTypeFieldNumber); + output->push_back(index()); + } else { + output->push_back(FileDescriptorProto::kEnumTypeFieldNumber); + output->push_back(index()); + } +} + +void EnumValueDescriptor::GetLocationPath(vector* output) const { + type()->GetLocationPath(output); + output->push_back(EnumDescriptorProto::kValueFieldNumber); + output->push_back(index()); +} + +void ServiceDescriptor::GetLocationPath(vector* output) const { + output->push_back(FileDescriptorProto::kServiceFieldNumber); + output->push_back(index()); +} + +void MethodDescriptor::GetLocationPath(vector* output) const { + service()->GetLocationPath(output); + output->push_back(ServiceDescriptorProto::kMethodFieldNumber); + output->push_back(index()); +} + // =================================================================== namespace { @@ -1857,6 +2303,11 @@ class DescriptorBuilder { string filename_; FileDescriptor* file_; FileDescriptorTables* file_tables_; + set dependencies_; + + // unused_dependency_ is used to record the unused imported files. + // Note: public import is not considered. + set unused_dependency_; // If LookupSymbol() finds a symbol that is in a file which is not a declared // dependency of this file, it will fail, but will set @@ -1868,10 +2319,22 @@ class DescriptorBuilder { const FileDescriptor* possible_undeclared_dependency_; string possible_undeclared_dependency_name_; + // If LookupSymbol() could resolve a symbol which is not defined, + // record the resolved name. This is only used by AddNotDefinedError() + // to report a more useful error message. + string undefine_resolved_name_; + void AddError(const string& element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, const string& error); + void AddError(const string& element_name, + const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const char* error); + void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here); + void AddTwiceListedError(const FileDescriptorProto& proto, int index); + void AddImportError(const FileDescriptorProto& proto, int index); // Adds an error indicating that undefined_symbol was not defined. Must // only be called after LookupSymbol() fails. @@ -1881,11 +2344,19 @@ class DescriptorBuilder { DescriptorPool::ErrorCollector::ErrorLocation location, const string& undefined_symbol); + void AddWarning(const string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const string& error); + // Silly helper which determines if the given file is in the given package. // I.e., either file->package() == package_name or file->package() is a // nested package within package_name. bool IsInPackage(const FileDescriptor* file, const string& package_name); + // Helper function which finds all public dependencies of the given file, and + // stores the them in the dependencies_ set in the builder. + void RecordPublicDependencies(const FileDescriptor* file); + // Like tables_->FindSymbol(), but additionally: // - Search the pool's underlay if not found in tables_. // - Insure that the resulting Symbol is from one of the file's declared @@ -1896,6 +2367,10 @@ class DescriptorBuilder { // file's declared dependencies. Symbol FindSymbolNotEnforcingDeps(const string& name); + // This implements the body of FindSymbolNotEnforcingDeps(). + Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool, + const string& name); + // Like FindSymbol(), but looks up the name relative to some other symbol // name. This first searches siblings of relative_to, then siblings of its // parents, etc. For example, LookupSymbol("foo.bar", "baz.qux.corge") makes @@ -2007,6 +2482,9 @@ class DescriptorBuilder { void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto, const Descriptor* parent, Descriptor::ExtensionRange* result); + void BuildOneof(const OneofDescriptorProto& proto, + Descriptor* parent, + OneofDescriptor* result); void BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent, EnumDescriptor* result); @@ -2020,6 +2498,8 @@ class DescriptorBuilder { const ServiceDescriptor* parent, MethodDescriptor* result); + void LogUnusedDependency(const FileDescriptor* result); + // Must be run only after building. // // NOTE: Options will not be available during cross-linking, as they @@ -2056,6 +2536,8 @@ class DescriptorBuilder { // Otherwise returns true. bool InterpretOptions(OptionsToInterpret* options_to_interpret); + class AggregateOptionFinder; + private: // Interprets uninterpreted_option_ on the specified message, which // must be the mutable copy of the original options message to which @@ -2082,6 +2564,11 @@ class DescriptorBuilder { bool SetOptionValue(const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields); + // Parses an aggregate value for a CPPTYPE_MESSAGE option and + // saves it into *unknown_fields. + bool SetAggregateOption(const FieldDescriptor* option_field, + UnknownFieldSet* unknown_fields); + // Convenience functions to set an int field the right way, depending on // its wire type (a single int CppType can represent multiple wire types). void SetInt32(int number, int32 value, FieldDescriptor::Type type, @@ -2128,6 +2615,10 @@ class DescriptorBuilder { // can use it to find locations recorded by the parser. const UninterpretedOption* uninterpreted_option_; + // Factory used to create the dynamic messages we need to parse + // any aggregate option values we encounter. + DynamicMessageFactory dynamic_factory_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter); }; @@ -2139,12 +2630,22 @@ class DescriptorBuilder { // redundantly declare OptionInterpreter a friend just to make things extra // clear for these bad compilers. friend class OptionInterpreter; + friend class OptionInterpreter::AggregateOptionFinder; + static inline bool get_allow_unknown(const DescriptorPool* pool) { return pool->allow_unknown_; } + static inline bool get_enforce_weak(const DescriptorPool* pool) { + return pool->enforce_weak_; + } static inline bool get_is_placeholder(const Descriptor* descriptor) { return descriptor->is_placeholder_; } + static inline void assert_mutex_held(const DescriptorPool* pool) { + if (pool->mutex_ != NULL) { + pool->mutex_->AssertHeld(); + } + } // Must be run only after options have been interpreted. // @@ -2169,6 +2670,7 @@ class DescriptorBuilder { void ValidateMapKey(FieldDescriptor* field, const FieldDescriptorProto& proto); + }; const FileDescriptor* DescriptorPool::BuildFile( @@ -2178,6 +2680,8 @@ const FileDescriptor* DescriptorPool::BuildFile( "DescriptorDatabase. You must instead find a way to get your file " "into the underlying database."; GOOGLE_CHECK(mutex_ == NULL); // Implied by the above GOOGLE_CHECK. + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); return DescriptorBuilder(this, tables_.get(), NULL).BuildFile(proto); } @@ -2189,6 +2693,8 @@ const FileDescriptor* DescriptorPool::BuildFileCollectingErrors( "DescriptorDatabase. You must instead find a way to get your file " "into the underlying database."; GOOGLE_CHECK(mutex_ == NULL); // Implied by the above GOOGLE_CHECK. + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); return DescriptorBuilder(this, tables_.get(), error_collector).BuildFile(proto); } @@ -2196,8 +2702,16 @@ const FileDescriptor* DescriptorPool::BuildFileCollectingErrors( const FileDescriptor* DescriptorPool::BuildFileFromDatabase( const FileDescriptorProto& proto) const { mutex_->AssertHeld(); - return DescriptorBuilder(this, tables_.get(), - default_error_collector_).BuildFile(proto); + if (tables_->known_bad_files_.count(proto.name()) > 0) { + return NULL; + } + const FileDescriptor* result = + DescriptorBuilder(this, tables_.get(), + default_error_collector_).BuildFile(proto); + if (result == NULL) { + tables_->known_bad_files_.insert(proto.name()); + } + return result; } DescriptorBuilder::DescriptorBuilder( @@ -2208,7 +2722,8 @@ DescriptorBuilder::DescriptorBuilder( tables_(tables), error_collector_(error_collector), had_errors_(false), - possible_undeclared_dependency_(NULL) {} + possible_undeclared_dependency_(NULL), + undefine_resolved_name_("") {} DescriptorBuilder::~DescriptorBuilder() {} @@ -2230,21 +2745,53 @@ void DescriptorBuilder::AddError( had_errors_ = true; } +void DescriptorBuilder::AddError( + const string& element_name, + const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const char* error) { + AddError(element_name, descriptor, location, string(error)); +} + void DescriptorBuilder::AddNotDefinedError( const string& element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, const string& undefined_symbol) { - if (possible_undeclared_dependency_ == NULL) { + if (possible_undeclared_dependency_ == NULL && + undefine_resolved_name_.empty()) { AddError(element_name, descriptor, location, "\"" + undefined_symbol + "\" is not defined."); } else { - AddError(element_name, descriptor, location, - "\"" + possible_undeclared_dependency_name_ + - "\" seems to be defined in \"" + - possible_undeclared_dependency_->name() + "\", which is not " - "imported by \"" + filename_ + "\". To use it here, please " - "add the necessary import."); + if (possible_undeclared_dependency_ != NULL) { + AddError(element_name, descriptor, location, + "\"" + possible_undeclared_dependency_name_ + + "\" seems to be defined in \"" + + possible_undeclared_dependency_->name() + "\", which is not " + "imported by \"" + filename_ + "\". To use it here, please " + "add the necessary import."); + } + if (!undefine_resolved_name_.empty()) { + AddError(element_name, descriptor, location, + "\"" + undefined_symbol + "\" is resolved to \"" + + undefine_resolved_name_ + "\", which is not defined. " + "The innermost scope is searched first in name resolution. " + "Consider using a leading '.'(i.e., \"." + + undefined_symbol + + "\") to start from the outermost scope."); + } + } +} + +void DescriptorBuilder::AddWarning( + const string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const string& error) { + if (error_collector_ == NULL) { + GOOGLE_LOG(WARNING) << filename_ << " " << element_name << ": " << error; + } else { + error_collector_->AddWarning(filename_, element_name, &descriptor, location, + error); } } @@ -2255,31 +2802,48 @@ bool DescriptorBuilder::IsInPackage(const FileDescriptor* file, file->package()[package_name.size()] == '.'); } -Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const string& name) { - Symbol result; +void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) { + if (file == NULL || !dependencies_.insert(file).second) return; + for (int i = 0; file != NULL && i < file->public_dependency_count(); i++) { + RecordPublicDependencies(file->public_dependency(i)); + } +} - // We need to search our pool and all its underlays. - const DescriptorPool* pool = pool_; - while (true) { - // If we are looking at an underlay, we must lock its mutex_, since we are - // accessing the underlay's tables_ dircetly. - MutexLockMaybe lock((pool == pool_) ? NULL : pool->mutex_); +Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper( + const DescriptorPool* pool, const string& name) { + // If we are looking at an underlay, we must lock its mutex_, since we are + // accessing the underlay's tables_ directly. + MutexLockMaybe lock((pool == pool_) ? NULL : pool->mutex_); + + Symbol result = pool->tables_->FindSymbol(name); + if (result.IsNull() && pool->underlay_ != NULL) { + // Symbol not found; check the underlay. + result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name); + } - // Note that we don't have to check fallback_database_ here because the - // symbol has to be in one of its file's direct dependencies, and we have - // already loaded those by the time we get here. - result = pool->tables_->FindSymbol(name); - if (!result.IsNull()) break; - if (pool->underlay_ == NULL) return kNullSymbol; - pool = pool->underlay_; + if (result.IsNull()) { + // In theory, we shouldn't need to check fallback_database_ because the + // symbol should be in one of its file's direct dependencies, and we have + // already loaded those by the time we get here. But we check anyway so + // that we can generate better error message when dependencies are missing + // (i.e., "missing dependency" rather than "type is not defined"). + if (pool->TryFindSymbolInFallbackDatabase(name)) { + result = pool->tables_->FindSymbol(name); + } } return result; } +Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const string& name) { + return FindSymbolNotEnforcingDepsHelper(pool_, name); +} + Symbol DescriptorBuilder::FindSymbol(const string& name) { Symbol result = FindSymbolNotEnforcingDeps(name); + if (result.IsNull()) return result; + if (!pool_->enforce_dependencies_) { // Hack for CompilerUpgrader. return result; @@ -2288,9 +2852,9 @@ Symbol DescriptorBuilder::FindSymbol(const string& name) { // Only find symbols which were defined in this file or one of its // dependencies. const FileDescriptor* file = result.GetFile(); - if (file == file_) return result; - for (int i = 0; i < file_->dependency_count(); i++) { - if (file == file_->dependency(i)) return result; + if (file == file_ || dependencies_.count(file) > 0) { + unused_dependency_.erase(file); + return result; } if (result.type == Symbol::PACKAGE) { @@ -2302,12 +2866,10 @@ Symbol DescriptorBuilder::FindSymbol(const string& name) { // dependency also defines the same package. We can't really rule out this // symbol unless none of the dependencies define it. if (IsInPackage(file_, name)) return result; - for (int i = 0; i < file_->dependency_count(); i++) { + for (set::const_iterator it = dependencies_.begin(); + it != dependencies_.end(); ++it) { // Note: A dependency may be NULL if it was not found or had errors. - if (file_->dependency(i) != NULL && - IsInPackage(file_->dependency(i), name)) { - return result; - } + if (*it != NULL && IsInPackage(*it, name)) return result; } } @@ -2319,6 +2881,7 @@ Symbol DescriptorBuilder::FindSymbol(const string& name) { Symbol DescriptorBuilder::LookupSymbolNoPlaceholder( const string& name, const string& relative_to, ResolveMode resolve_mode) { possible_undeclared_dependency_ = NULL; + undefine_resolved_name_.clear(); if (name.size() > 0 && name[0] == '.') { // Fully-qualified name. @@ -2336,7 +2899,7 @@ Symbol DescriptorBuilder::LookupSymbolNoPlaceholder( // } // So, we look for just "Foo" first, then look for "Bar.baz" within it if // found. - int name_dot_pos = name.find_first_of('.'); + string::size_type name_dot_pos = name.find_first_of('.'); string first_part_of_name; if (name_dot_pos == string::npos) { first_part_of_name = name; @@ -2367,7 +2930,11 @@ Symbol DescriptorBuilder::LookupSymbolNoPlaceholder( if (result.IsAggregate()) { scope_to_try.append(name, first_part_of_name.size(), name.size() - first_part_of_name.size()); - return FindSymbol(scope_to_try); + result = FindSymbol(scope_to_try); + if (result.IsNull()) { + undefine_resolved_name_ = scope_to_try; + } + return result; } else { // We found a symbol but it's not an aggregate. Continue the loop. } @@ -2420,7 +2987,7 @@ Symbol DescriptorBuilder::NewPlaceholder(const string& name, placeholder_name = tables_->AllocateString( placeholder_full_name->substr(dotpos + 1)); } else { - placeholder_package = &kEmptyString; + placeholder_package = &internal::GetEmptyString(); placeholder_name = placeholder_full_name; } @@ -2428,12 +2995,15 @@ Symbol DescriptorBuilder::NewPlaceholder(const string& name, FileDescriptor* placeholder_file = tables_->Allocate(); memset(placeholder_file, 0, sizeof(*placeholder_file)); + placeholder_file->source_code_info_ = &SourceCodeInfo::default_instance(); + placeholder_file->name_ = tables_->AllocateString(*placeholder_full_name + ".placeholder.proto"); placeholder_file->package_ = placeholder_package; placeholder_file->pool_ = pool_; placeholder_file->options_ = &FileOptions::default_instance(); placeholder_file->tables_ = &FileDescriptorTables::kEmpty; + placeholder_file->is_placeholder_ = true; // All other fields are zero or NULL. if (placeholder_type == PLACEHOLDER_ENUM) { @@ -2504,10 +3074,11 @@ const FileDescriptor* DescriptorBuilder::NewPlaceholderFile( memset(placeholder, 0, sizeof(*placeholder)); placeholder->name_ = tables_->AllocateString(name); - placeholder->package_ = &kEmptyString; + placeholder->package_ = &internal::GetEmptyString(); placeholder->pool_ = pool_; placeholder->options_ = &FileOptions::default_instance(); placeholder->tables_ = &FileDescriptorTables::kEmpty; + placeholder->is_placeholder_ = true; // All other fields are zero or NULL. return placeholder; @@ -2648,7 +3219,11 @@ template void DescriptorBuilder::AllocateOptionsImpl( // tables_->AllocateMessage(); typename DescriptorT::OptionsType* const dummy = NULL; typename DescriptorT::OptionsType* options = tables_->AllocateMessage(dummy); - options->CopyFrom(orig_options); + // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti + // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the + // reflection based method, which requires the Descriptor. However, we are in + // the middle of building the descriptors, thus the deadlock. + options->ParseFromString(orig_options.SerializeAsString()); descriptor->options_ = options; // Don't add to options_to_interpret_ unless there were uninterpreted @@ -2674,6 +3249,45 @@ template void DescriptorBuilder::AllocateOptionsImpl( METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i); \ } +void DescriptorBuilder::AddRecursiveImportError( + const FileDescriptorProto& proto, int from_here) { + string error_message("File recursively imports itself: "); + for (int i = from_here; i < tables_->pending_files_.size(); i++) { + error_message.append(tables_->pending_files_[i]); + error_message.append(" -> "); + } + error_message.append(proto.name()); + + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, + error_message); +} + +void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto, + int index) { + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, + "Import \"" + proto.dependency(index) + "\" was listed twice."); +} + +void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto, + int index) { + string message; + if (pool_->fallback_database_ == NULL) { + message = "Import \"" + proto.dependency(index) + + "\" has not been loaded."; + } else { + message = "Import \"" + proto.dependency(index) + + "\" was not found or had errors."; + } + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, message); +} + +static bool ExistingFileMatchesProto(const FileDescriptor* existing_file, + const FileDescriptorProto& proto) { + FileDescriptorProto existing_proto; + existing_file->CopyTo(&existing_proto); + return existing_proto.SerializeAsString() == proto.SerializeAsString(); +} + const FileDescriptor* DescriptorBuilder::BuildFile( const FileDescriptorProto& proto) { filename_ = proto.name(); @@ -2686,9 +3300,7 @@ const FileDescriptor* DescriptorBuilder::BuildFile( const FileDescriptor* existing_file = tables_->FindFile(filename_); if (existing_file != NULL) { // File already in pool. Compare the existing one to the input. - FileDescriptorProto existing_proto; - existing_file->CopyTo(&existing_proto); - if (existing_proto.SerializeAsString() == proto.SerializeAsString()) { + if (ExistingFileMatchesProto(existing_file, proto)) { // They're identical. Return the existing descriptor. return existing_file; } @@ -2707,15 +3319,7 @@ const FileDescriptor* DescriptorBuilder::BuildFile( // at all. for (int i = 0; i < tables_->pending_files_.size(); i++) { if (tables_->pending_files_[i] == proto.name()) { - string error_message("File recursively imports itself: "); - for (; i < tables_->pending_files_.size(); i++) { - error_message.append(tables_->pending_files_[i]); - error_message.append(" -> "); - } - error_message.append(proto.name()); - - AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, - error_message); + AddRecursiveImportError(proto, i); return NULL; } } @@ -2737,11 +3341,20 @@ const FileDescriptor* DescriptorBuilder::BuildFile( } // Checkpoint the tables so that we can roll back if something goes wrong. - tables_->Checkpoint(); + tables_->AddCheckpoint(); FileDescriptor* result = tables_->Allocate(); file_ = result; + result->is_placeholder_ = false; + if (proto.has_source_code_info()) { + SourceCodeInfo *info = tables_->AllocateMessage(); + info->CopyFrom(proto.source_code_info()); + result->source_code_info_ = info; + } else { + result->source_code_info_ = &SourceCodeInfo::default_instance(); + } + file_tables_ = tables_->AllocateFileTables(); file_->tables_ = file_tables_; @@ -2768,7 +3381,7 @@ const FileDescriptor* DescriptorBuilder::BuildFile( "A file with this name is already in the pool."); // Bail out early so that if this is actually the exact same file, we // don't end up reporting that every single symbol is already defined. - tables_->Rollback(); + tables_->RollbackToLastCheckpoint(); return NULL; } if (!result->package().empty()) { @@ -2780,11 +3393,14 @@ const FileDescriptor* DescriptorBuilder::BuildFile( result->dependency_count_ = proto.dependency_size(); result->dependencies_ = tables_->AllocateArray(proto.dependency_size()); + unused_dependency_.clear(); + set weak_deps; + for (int i = 0; i < proto.weak_dependency_size(); ++i) { + weak_deps.insert(proto.weak_dependency(i)); + } for (int i = 0; i < proto.dependency_size(); i++) { if (!seen_dependencies.insert(proto.dependency(i)).second) { - AddError(proto.name(), proto, - DescriptorPool::ErrorCollector::OTHER, - "Import \"" + proto.dependency(i) + "\" was listed twice."); + AddTwiceListedError(proto, i); } const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i)); @@ -2793,26 +3409,67 @@ const FileDescriptor* DescriptorBuilder::BuildFile( } if (dependency == NULL) { - if (pool_->allow_unknown_) { + if (pool_->allow_unknown_ || + (!pool_->enforce_weak_ && weak_deps.find(i) != weak_deps.end())) { dependency = NewPlaceholderFile(proto.dependency(i)); } else { - string message; - if (pool_->fallback_database_ == NULL) { - message = "Import \"" + proto.dependency(i) + - "\" has not been loaded."; - } else { - message = "Import \"" + proto.dependency(i) + - "\" was not found or had errors."; - } - AddError(proto.name(), proto, - DescriptorPool::ErrorCollector::OTHER, - message); + AddImportError(proto, i); + } + } else { + // Add to unused_dependency_ to track unused imported files. + // Note: do not track unused imported files for public import. + if (pool_->enforce_dependencies_ && + (pool_->unused_import_track_files_.find(proto.name()) != + pool_->unused_import_track_files_.end()) && + (dependency->public_dependency_count() == 0)) { + unused_dependency_.insert(dependency); } } result->dependencies_[i] = dependency; } + // Check public dependencies. + int public_dependency_count = 0; + result->public_dependencies_ = tables_->AllocateArray( + proto.public_dependency_size()); + for (int i = 0; i < proto.public_dependency_size(); i++) { + // Only put valid public dependency indexes. + int index = proto.public_dependency(i); + if (index >= 0 && index < proto.dependency_size()) { + result->public_dependencies_[public_dependency_count++] = index; + // Do not track unused imported files for public import. + unused_dependency_.erase(result->dependency(index)); + } else { + AddError(proto.name(), proto, + DescriptorPool::ErrorCollector::OTHER, + "Invalid public dependency index."); + } + } + result->public_dependency_count_ = public_dependency_count; + + // Build dependency set + dependencies_.clear(); + for (int i = 0; i < result->dependency_count(); i++) { + RecordPublicDependencies(result->dependency(i)); + } + + // Check weak dependencies. + int weak_dependency_count = 0; + result->weak_dependencies_ = tables_->AllocateArray( + proto.weak_dependency_size()); + for (int i = 0; i < proto.weak_dependency_size(); i++) { + int index = proto.weak_dependency(i); + if (index >= 0 && index < proto.dependency_size()) { + result->weak_dependencies_[weak_dependency_count++] = index; + } else { + AddError(proto.name(), proto, + DescriptorPool::ErrorCollector::OTHER, + "Invalid weak dependency index."); + } + } + result->weak_dependency_count_ = weak_dependency_count; + // Convert children. BUILD_ARRAY(proto, result, message_type, BuildMessage , NULL); BUILD_ARRAY(proto, result, enum_type , BuildEnum , NULL); @@ -2849,11 +3506,16 @@ const FileDescriptor* DescriptorBuilder::BuildFile( ValidateFileOptions(result, proto); } + + if (!unused_dependency_.empty()) { + LogUnusedDependency(result); + } + if (had_errors_) { - tables_->Rollback(); + tables_->RollbackToLastCheckpoint(); return NULL; } else { - tables_->Checkpoint(); + tables_->ClearLastCheckpoint(); return result; } } @@ -2876,6 +3538,8 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, result->is_placeholder_ = false; result->is_unqualified_placeholder_ = false; + // Build oneofs first so that fields and extension ranges can refer to them. + BUILD_ARRAY(proto, result, oneof_decl , BuildOneof , result); BUILD_ARRAY(proto, result, field , BuildField , result); BUILD_ARRAY(proto, result, nested_type , BuildMessage , result); BUILD_ARRAY(proto, result, enum_type , BuildEnum , result); @@ -2966,6 +3630,19 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->label_ = static_cast( implicit_cast(proto.label())); + // An extension cannot have a required field (b/13365836). + if (result->is_extension_ && + result->label_ == FieldDescriptor::LABEL_REQUIRED) { + AddError(result->full_name(), proto, + // Error location `TYPE`: we would really like to indicate + // `LABEL`, but the `ErrorLocation` enum has no entry for this, and + // we don't necessarily know about all implementations of the + // `ErrorCollector` interface to extend them to handle the new + // error location type properly. + DescriptorPool::ErrorCollector::TYPE, + "Message extensions cannot have required fields."); + } + // Some of these may be filled in when cross-linking. result->containing_type_ = NULL; result->extension_scope_ = NULL; @@ -3009,7 +3686,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->default_value_float_ = numeric_limits::quiet_NaN(); } else { result->default_value_float_ = - NoLocaleStrtod(proto.default_value().c_str(), &end_pos); + io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos); } break; case FieldDescriptor::CPPTYPE_DOUBLE: @@ -3021,7 +3698,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->default_value_double_ = numeric_limits::quiet_NaN(); } else { result->default_value_double_ = - NoLocaleStrtod(proto.default_value().c_str(), &end_pos); + io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos); } break; case FieldDescriptor::CPPTYPE_BOOL: @@ -3045,7 +3722,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, UnescapeCEscapeString(proto.default_value())); } else { result->default_value_string_ = - tables_->AllocateString(proto.default_value()); + tables_->AllocateString(proto.default_value()); } break; case FieldDescriptor::CPPTYPE_MESSAGE: @@ -3063,7 +3740,8 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, if (proto.default_value().empty() || *end_pos != '\0') { AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::DEFAULT_VALUE, - "Couldn't parse default value."); + "Couldn't parse default value \"" + proto.default_value() + + "\"."); } } } else { @@ -3095,7 +3773,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->default_value_enum_ = NULL; break; case FieldDescriptor::CPPTYPE_STRING: - result->default_value_string_ = &kEmptyString; + result->default_value_string_ = &internal::GetEmptyString(); break; case FieldDescriptor::CPPTYPE_MESSAGE: break; @@ -3106,7 +3784,15 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, if (result->number() <= 0) { AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, "Field numbers must be positive integers."); - } else if (result->number() > FieldDescriptor::kMaxNumber) { + } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) { + // Only validate that the number is within the valid field range if it is + // not an extension. Since extension numbers are validated with the + // extendee's valid set of extension numbers, and those are in turn + // validated against the max allowed number, the check is unnecessary for + // extension fields. + // This avoids cross-linking issues that arise when attempting to check if + // the extendee is a message_set_wire_format message, which has a higher max + // on extension numbers. AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, strings::Substitute("Field numbers cannot be greater than $0.", FieldDescriptor::kMaxNumber)); @@ -3128,6 +3814,16 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, } result->extension_scope_ = parent; + + if (proto.has_oneof_index()) { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::OTHER, + "FieldDescriptorProto.oneof_index should not be set for " + "extensions."); + } + + // Fill in later (maybe). + result->containing_oneof_ = NULL; } else { if (proto.has_extendee()) { AddError(result->full_name(), proto, @@ -3136,6 +3832,23 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, } result->containing_type_ = parent; + + if (proto.has_oneof_index()) { + if (proto.oneof_index() < 0 || + proto.oneof_index() >= parent->oneof_decl_count()) { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::OTHER, + strings::Substitute("FieldDescriptorProto.oneof_index $0 is " + "out of range for type \"$1\".", + proto.oneof_index(), + parent->name())); + result->containing_oneof_ = NULL; + } else { + result->containing_oneof_ = parent->oneof_decl(proto.oneof_index()); + } + } else { + result->containing_oneof_ = NULL; + } } // Copy options. @@ -3161,12 +3874,10 @@ void DescriptorBuilder::BuildExtensionRange( "Extension numbers must be positive integers."); } - if (result->end > FieldDescriptor::kMaxNumber + 1) { - AddError(parent->full_name(), proto, - DescriptorPool::ErrorCollector::NUMBER, - strings::Substitute("Extension numbers cannot be greater than $0.", - FieldDescriptor::kMaxNumber)); - } + // Checking of the upper bound of the extension range is deferred until after + // options interpreting. This allows messages with message_set_wire_format to + // have extensions beyond FieldDescriptor::kMaxNumber, since the extension + // numbers are actually used as int32s in the message_set_wire_format. if (result->start >= result->end) { AddError(parent->full_name(), proto, @@ -3175,6 +3886,28 @@ void DescriptorBuilder::BuildExtensionRange( } } +void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto, + Descriptor* parent, + OneofDescriptor* result) { + string* full_name = tables_->AllocateString(parent->full_name()); + full_name->append(1, '.'); + full_name->append(proto.name()); + + ValidateSymbolName(proto.name(), *full_name, proto); + + result->name_ = tables_->AllocateString(proto.name()); + result->full_name_ = full_name; + + result->containing_type_ = parent; + + // We need to fill these in later. + result->field_count_ = 0; + result->fields_ = NULL; + + AddSymbol(result->full_name(), parent, result->name(), + proto, Symbol(result)); +} + void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent, EnumDescriptor* result) { @@ -3283,7 +4016,7 @@ void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto, } void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto, - const void* dummy, + const void* /* dummy */, ServiceDescriptor* result) { string* full_name = tables_->AllocateString(file_->package()); if (!full_name->empty()) full_name->append(1, '.'); @@ -3384,6 +4117,46 @@ void DescriptorBuilder::CrossLinkMessage( for (int i = 0; i < message->extension_count(); i++) { CrossLinkField(&message->extensions_[i], proto.extension(i)); } + + // Set up field array for each oneof. + + // First count the number of fields per oneof. + for (int i = 0; i < message->field_count(); i++) { + const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof(); + if (oneof_decl != NULL) { + // Must go through oneof_decls_ array to get a non-const version of the + // OneofDescriptor. + ++message->oneof_decls_[oneof_decl->index()].field_count_; + } + } + + // Then allocate the arrays. + for (int i = 0; i < message->oneof_decl_count(); i++) { + OneofDescriptor* oneof_decl = &message->oneof_decls_[i]; + + if (oneof_decl->field_count() == 0) { + AddError(message->full_name() + "." + oneof_decl->name(), + proto.oneof_decl(i), + DescriptorPool::ErrorCollector::NAME, + "Oneof must have at least one field."); + } + + oneof_decl->fields_ = + tables_->AllocateArray(oneof_decl->field_count_); + oneof_decl->field_count_ = 0; + } + + // Then fill them in. + for (int i = 0; i < message->field_count(); i++) { + const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof(); + if (oneof_decl != NULL) { + OneofDescriptor* mutable_oneof_decl = + &message->oneof_decls_[oneof_decl->index()]; + message->fields_[i].index_in_oneof_ = mutable_oneof_decl->field_count_; + mutable_oneof_decl->fields_[mutable_oneof_decl->field_count_++] = + message->field(i); + } + } } void DescriptorBuilder::CrossLinkField( @@ -3408,7 +4181,10 @@ void DescriptorBuilder::CrossLinkField( } field->containing_type_ = extendee.descriptor; - if (!field->containing_type()->IsExtensionNumber(field->number())) { + const Descriptor::ExtensionRange* extension_range = field->containing_type() + ->FindExtensionRangeContainingNumber(field->number()); + + if (extension_range == NULL) { AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, strings::Substitute("\"$0\" does not declare $1 as an " @@ -3418,6 +4194,17 @@ void DescriptorBuilder::CrossLinkField( } } + if (field->containing_oneof() != NULL) { + if (field->label() != FieldDescriptor::LABEL_OPTIONAL) { + // Note that this error will never happen when parsing .proto files. + // It can only happen if you manually construct a FileDescriptorProto + // that is incorrect. + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::NAME, + "Fields of oneofs must themselves have label LABEL_OPTIONAL."); + } + } + if (proto.has_type_name()) { // Assume we are expecting a message type unless the proto contains some // evidence that it expects an enum type. This only makes a difference if @@ -3430,6 +4217,11 @@ void DescriptorBuilder::CrossLinkField( expecting_enum ? PLACEHOLDER_ENUM : PLACEHOLDER_MESSAGE, LOOKUP_TYPES); + // If the type is a weak type, we change the type to a google.protobuf.Empty field. + if (type.IsNull() && !pool_->enforce_weak_ && proto.options().weak()) { + type = FindSymbol(kNonLinkedWeakMessageReplacementName); + } + if (type.IsNull()) { AddNotDefinedError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, @@ -3481,21 +4273,34 @@ void DescriptorBuilder::CrossLinkField( } if (field->has_default_value()) { - // We can't just use field->enum_type()->FindValueByName() here - // because that locks the pool's mutex, which we have already locked - // at this point. - Symbol default_value = - LookupSymbolNoPlaceholder(proto.default_value(), - field->enum_type()->full_name()); - - if (default_value.type == Symbol::ENUM_VALUE && - default_value.enum_value_descriptor->type() == field->enum_type()) { - field->default_value_enum_ = default_value.enum_value_descriptor; - } else { + // Ensure that the default value is an identifier. Parser cannot always + // verify this because it does not have complete type information. + // N.B. that this check yields better error messages but is not + // necessary for correctness (an enum symbol must be a valid identifier + // anyway), only for better errors. + if (!io::Tokenizer::IsIdentifier(proto.default_value())) { AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::DEFAULT_VALUE, - "Enum type \"" + field->enum_type()->full_name() + - "\" has no value named \"" + proto.default_value() + "\"."); + "Default value for an enum field must be an identifier."); + } else { + // We can't just use field->enum_type()->FindValueByName() here + // because that locks the pool's mutex, which we have already locked + // at this point. + Symbol default_value = + LookupSymbolNoPlaceholder(proto.default_value(), + field->enum_type()->full_name()); + + if (default_value.type == Symbol::ENUM_VALUE && + default_value.enum_value_descriptor->type() == + field->enum_type()) { + field->default_value_enum_ = default_value.enum_value_descriptor; + } else { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Enum type \"" + field->enum_type()->full_name() + + "\" has no value named \"" + proto.default_value() + + "\"."); + } } } else if (field->enum_type()->value_count() > 0) { // All enums must have at least one value, or we would have reported @@ -3539,12 +4344,26 @@ void DescriptorBuilder::CrossLinkField( field->containing_type()->full_name(), conflicting_field->name())); } - } - - if (field->is_extension()) { - // No need for error checking: if the extension number collided, - // we've already been informed of it by the if() above. - tables_->AddExtension(field); + } else { + if (field->is_extension()) { + if (!tables_->AddExtension(field)) { + const FieldDescriptor* conflicting_field = + tables_->FindExtension(field->containing_type(), field->number()); + string error_msg = strings::Substitute( + "Extension number $0 has already been used in \"$1\" by extension " + "\"$2\" defined in $3.", + field->number(), + field->containing_type()->full_name(), + conflicting_field->full_name(), + conflicting_field->file()->name()); + // Conflicting extension numbers should be an error. However, before + // turning this into an error we need to fix all existing broken + // protos first. + // TODO(xiaofeng): Change this to an error. + AddWarning(field->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, error_msg); + } + } } // Add the field to the lowercase-name and camelcase-name tables. @@ -3563,7 +4382,8 @@ void DescriptorBuilder::CrossLinkEnum( } void DescriptorBuilder::CrossLinkEnumValue( - EnumValueDescriptor* enum_value, const EnumValueDescriptorProto& proto) { + EnumValueDescriptor* enum_value, + const EnumValueDescriptorProto& /* proto */) { if (enum_value->options_ == NULL) { enum_value->options_ = &EnumValueOptions::default_instance(); } @@ -3627,7 +4447,6 @@ static bool IsLite(const FileDescriptor* file) { // TODO(kenton): I don't even remember how many of these conditions are // actually possible. I'm just being super-safe. return file != NULL && - &file->options() != NULL && &file->options() != &FileOptions::default_instance() && file->options().optimize_for() == FileOptions::LITE_RUNTIME; } @@ -3655,12 +4474,27 @@ void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file, } } + void DescriptorBuilder::ValidateMessageOptions(Descriptor* message, const DescriptorProto& proto) { VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field); VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message); VALIDATE_OPTIONS_FROM_ARRAY(message, enum_type, Enum); VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field); + + const int64 max_extension_range = + static_cast(message->options().message_set_wire_format() ? + kint32max : + FieldDescriptor::kMaxNumber); + for (int i = 0; i < message->extension_range_count(); ++i) { + if (message->extension_range(i)->end > max_extension_range + 1) { + AddError( + message->full_name(), proto.extension_range(i), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Extension numbers cannot be greater than $0.", + max_extension_range)); + } + } } void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field, @@ -3669,6 +4503,15 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field, ValidateMapKey(field, proto); } + // Only message type fields may be lazy. + if (field->options().lazy()) { + if (field->type() != FieldDescriptor::TYPE_MESSAGE) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + "[lazy = true] can only be specified for submessage fields."); + } + } + // Only repeated primitive fields may be packed. if (field->options().packed() && !field->is_packable()) { AddError( @@ -3707,30 +4550,61 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field, "files. Note that you cannot extend a non-lite type to contain " "a lite type, but the reverse is allowed."); } + } void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm, const EnumDescriptorProto& proto) { VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue); + if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) { + map used_values; + for (int i = 0; i < enm->value_count(); ++i) { + const EnumValueDescriptor* enum_value = enm->value(i); + if (used_values.find(enum_value->number()) != used_values.end()) { + string error = + "\"" + enum_value->full_name() + + "\" uses the same enum value as \"" + + used_values[enum_value->number()] + "\". If this is intended, set " + "'option allow_alias = true;' to the enum definition."; + if (!enm->options().allow_alias()) { + // Generate error if duplicated enum values are explicitly disallowed. + AddError(enm->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, + error); + } else { + // Generate warning if duplicated values are found but the option + // isn't set. + GOOGLE_LOG(ERROR) << error; + } + } else { + used_values[enum_value->number()] = enum_value->full_name(); + } + } + } } void DescriptorBuilder::ValidateEnumValueOptions( - EnumValueDescriptor* enum_value, const EnumValueDescriptorProto& proto) { + EnumValueDescriptor* /* enum_value */, + const EnumValueDescriptorProto& /* proto */) { // Nothing to do so far. } void DescriptorBuilder::ValidateServiceOptions(ServiceDescriptor* service, const ServiceDescriptorProto& proto) { - if (IsLite(service->file())) { + if (IsLite(service->file()) && + (service->file()->options().cc_generic_services() || + service->file()->options().java_generic_services())) { AddError(service->full_name(), proto, DescriptorPool::ErrorCollector::NAME, - "Files with optimize_for = LITE_RUNTIME cannot define services."); + "Files with optimize_for = LITE_RUNTIME cannot define services " + "unless you set both options cc_generic_services and " + "java_generic_sevices to false."); } VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method); } -void DescriptorBuilder::ValidateMethodOptions(MethodDescriptor* method, - const MethodDescriptorProto& proto) { +void DescriptorBuilder::ValidateMethodOptions(MethodDescriptor* /* method */, + const MethodDescriptorProto& /* proto */) { // Nothing to do so far. } @@ -3787,6 +4661,7 @@ void DescriptorBuilder::ValidateMapKey(FieldDescriptor* field, field->experimental_map_key_ = key_field; } + #undef VALIDATE_OPTIONS_FROM_ARRAY // ------------------------------------------------------------------- @@ -3877,9 +4752,11 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( // file we're currently building. The descriptor should be there as long as // the file we're building imported "google/protobuf/descriptors.proto". - // Note that we use DescriptorBuilder::FindSymbol(), not + // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not // DescriptorPool::FindMessageTypeByName() because we're already holding the - // pool's mutex, and the latter method locks it again. + // pool's mutex, and the latter method locks it again. We don't use + // FindSymbol() because files that use custom options only need to depend on + // the file that defines the option, not descriptor.proto itself. Symbol symbol = builder_->FindSymbolNotEnforcingDeps( options->GetDescriptor()->full_name()); if (!symbol.IsNull() && symbol.type == Symbol::MESSAGE) { @@ -3915,8 +4792,8 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows // relative lookups, and 2) because we're already holding the pool's // mutex, and the latter method locks it again. - Symbol symbol = builder_->LookupSymbol(name_part, - options_to_interpret_->name_scope); + symbol = builder_->LookupSymbol(name_part, + options_to_interpret_->name_scope); if (!symbol.IsNull() && symbol.type == Symbol::FIELD) { field = symbol.field_descriptor; } @@ -3936,6 +4813,15 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( // so we will just leave it as uninterpreted. AddWithoutInterpreting(*uninterpreted_option_, options); return true; + } else if (!(builder_->undefine_resolved_name_).empty()) { + // Option is resolved to a name which is not defined. + return AddNameError( + "Option \"" + debug_msg_name + "\" is resolved to \"(" + + builder_->undefine_resolved_name_ + + ")\", which is not defined. The innermost scope is searched first " + "in name resolution. Consider using a leading '.'(i.e., \"(." + + debug_msg_name.substr(1) + + "\") to start from the outermost scope."); } else { return AddNameError("Option \"" + debug_msg_name + "\" unknown."); } @@ -3956,22 +4842,20 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( "\" is not a field or extension of message \"" + descriptor->name() + "\"."); } - } else if (field->is_repeated()) { - return AddNameError("Option field \"" + debug_msg_name + - "\" is repeated. Repeated options are not " - "supported."); } else if (i < uninterpreted_option_->name_size() - 1) { if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { return AddNameError("Option \"" + debug_msg_name + "\" is an atomic type, not a message."); + } else if (field->is_repeated()) { + return AddNameError("Option field \"" + debug_msg_name + + "\" is a repeated message. Repeated message " + "options must be initialized using an " + "aggregate value."); } else { // Drill down into the submessage. intermediate_fields.push_back(field); descriptor = field->message_type(); } - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - return AddNameError("Option field \"" + debug_msg_name + - "\" cannot be of message type."); } } @@ -3983,7 +4867,7 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( // known will populate them correctly. // First see if the option is already set. - if (!ExamineIfOptionIsSet( + if (!field->is_repeated() && !ExamineIfOptionIsSet( intermediate_fields.begin(), intermediate_fields.end(), field, debug_msg_name, @@ -4306,18 +5190,119 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( break; case FieldDescriptor::CPPTYPE_MESSAGE: - // We don't currently support defining a message-typed option, so we - // should never actually get here. - return AddValueError("Option \"" + option_field->full_name() + - "\" is a message. To set fields within it, use " - "syntax like \"" + option_field->name() + - ".foo = value\"."); + if (!SetAggregateOption(option_field, unknown_fields)) { + return false; + } break; } return true; } +class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder + : public TextFormat::Finder { + public: + DescriptorBuilder* builder_; + + virtual const FieldDescriptor* FindExtension( + Message* message, const string& name) const { + assert_mutex_held(builder_->pool_); + const Descriptor* descriptor = message->GetDescriptor(); + Symbol result = builder_->LookupSymbolNoPlaceholder( + name, descriptor->full_name()); + if (result.type == Symbol::FIELD && + result.field_descriptor->is_extension()) { + return result.field_descriptor; + } else if (result.type == Symbol::MESSAGE && + descriptor->options().message_set_wire_format()) { + const Descriptor* foreign_type = result.descriptor; + // The text format allows MessageSet items to be specified using + // the type name, rather than the extension identifier. If the symbol + // lookup returned a Message, and the enclosing Message has + // message_set_wire_format = true, then return the message set + // extension, if one exists. + for (int i = 0; i < foreign_type->extension_count(); i++) { + const FieldDescriptor* extension = foreign_type->extension(i); + if (extension->containing_type() == descriptor && + extension->type() == FieldDescriptor::TYPE_MESSAGE && + extension->is_optional() && + extension->message_type() == foreign_type) { + // Found it. + return extension; + } + } + } + return NULL; + } +}; + +// A custom error collector to record any text-format parsing errors +namespace { +class AggregateErrorCollector : public io::ErrorCollector { + public: + string error_; + + virtual void AddError(int /* line */, int /* column */, + const string& message) { + if (!error_.empty()) { + error_ += "; "; + } + error_ += message; + } + + virtual void AddWarning(int /* line */, int /* column */, + const string& /* message */) { + // Ignore warnings + } +}; +} + +// We construct a dynamic message of the type corresponding to +// option_field, parse the supplied text-format string into this +// message, and serialize the resulting message to produce the value. +bool DescriptorBuilder::OptionInterpreter::SetAggregateOption( + const FieldDescriptor* option_field, + UnknownFieldSet* unknown_fields) { + if (!uninterpreted_option_->has_aggregate_value()) { + return AddValueError("Option \"" + option_field->full_name() + + "\" is a message. To set the entire message, use " + "syntax like \"" + option_field->name() + + " = { }\". " + "To set fields within it, use " + "syntax like \"" + option_field->name() + + ".foo = value\"."); + } + + const Descriptor* type = option_field->message_type(); + scoped_ptr dynamic(dynamic_factory_.GetPrototype(type)->New()); + GOOGLE_CHECK(dynamic.get() != NULL) + << "Could not create an instance of " << option_field->DebugString(); + + AggregateErrorCollector collector; + AggregateOptionFinder finder; + finder.builder_ = builder_; + TextFormat::Parser parser; + parser.RecordErrorsTo(&collector); + parser.SetFinder(&finder); + if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(), + dynamic.get())) { + AddValueError("Error while parsing option value for \"" + + option_field->name() + "\": " + collector.error_); + return false; + } else { + string serial; + dynamic->SerializeToString(&serial); // Never fails + if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) { + unknown_fields->AddLengthDelimited(option_field->number(), serial); + } else { + GOOGLE_CHECK_EQ(option_field->type(), FieldDescriptor::TYPE_GROUP); + UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number()); + group->ParseFromString(serial); + } + return true; + } +} + void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value, FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) { switch (type) { @@ -4397,5 +5382,39 @@ void DescriptorBuilder::OptionInterpreter::SetUInt64(int number, uint64 value, } } +void DescriptorBuilder::LogUnusedDependency(const FileDescriptor* result) { + + if (!unused_dependency_.empty()) { + std::set annotation_extensions; + annotation_extensions.insert("google.protobuf.MessageOptions"); + annotation_extensions.insert("google.protobuf.FileOptions"); + annotation_extensions.insert("google.protobuf.FieldOptions"); + annotation_extensions.insert("google.protobuf.EnumOptions"); + annotation_extensions.insert("google.protobuf.EnumValueOptions"); + annotation_extensions.insert("google.protobuf.ServiceOptions"); + annotation_extensions.insert("google.protobuf.MethodOptions"); + annotation_extensions.insert("google.protobuf.StreamOptions"); + for (set::const_iterator + it = unused_dependency_.begin(); + it != unused_dependency_.end(); ++it) { + // Do not log warnings for proto files which extend annotations. + int i; + for (i = 0 ; i < (*it)->extension_count(); ++i) { + if (annotation_extensions.find( + (*it)->extension(i)->containing_type()->full_name()) + != annotation_extensions.end()) { + break; + } + } + // Log warnings for unused imported files. + if (i == (*it)->extension_count()) { + GOOGLE_LOG(WARNING) << "Warning: Unused import: \"" << result->name() + << "\" imports \"" << (*it)->name() + << "\" which is not used."; + } + } + } +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index 7f87dd8..f7ee179 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -54,6 +54,7 @@ #ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__ #define GOOGLE_PROTOBUF_DESCRIPTOR_H__ +#include #include #include #include @@ -65,6 +66,7 @@ namespace protobuf { // Defined in this file. class Descriptor; class FieldDescriptor; +class OneofDescriptor; class EnumDescriptor; class EnumValueDescriptor; class ServiceDescriptor; @@ -76,6 +78,7 @@ class DescriptorPool; // Defined in descriptor.proto class DescriptorProto; class FieldDescriptorProto; +class OneofDescriptorProto; class EnumDescriptorProto; class EnumValueDescriptorProto; class ServiceDescriptorProto; @@ -89,6 +92,7 @@ class ServiceOptions; class MethodOptions; class FileOptions; class UninterpretedOption; +class SourceCodeInfo; // Defined in message.h class Message; @@ -100,6 +104,20 @@ class FileDescriptorTables; // Defined in unknown_field_set.h. class UnknownField; +// NB, all indices are zero-based. +struct SourceLocation { + int start_line; + int end_line; + int start_column; + int end_column; + + // Doc comments found at the source location. + // TODO(kenton): Maybe this struct should have been named SourceInfo or + // something instead. Oh well. + string leading_comments; + string trailing_comments; +}; + // Describes a type of protocol message, or a particular group within a // message. To obtain the Descriptor for a given message object, call // Message::GetDescriptor(). Generated message classes also have a @@ -144,6 +162,11 @@ class LIBPROTOBUF_EXPORT Descriptor { // will be suitable for re-parsing. string DebugString() const; + // Returns true if this is a placeholder for an unknown type. This will + // only be the case if this descriptor comes from a DescriptorPool + // with AllowUnknownDependencies() set. + bool is_placeholder() const; + // Field stuff ----------------------------------------------------- // The number of fields in this message type. @@ -171,6 +194,15 @@ class LIBPROTOBUF_EXPORT Descriptor { const FieldDescriptor* FindFieldByCamelcaseName( const string& camelcase_name) const; + // The number of oneofs in this message type. + int oneof_decl_count() const; + // Get a oneof by index, where 0 <= index < oneof_decl_count(). + // These are returned in the order they were defined in the .proto file. + const OneofDescriptor* oneof_decl(int index) const; + + // Looks up a oneof by name. Returns NULL if no such oneof exists. + const OneofDescriptor* FindOneofByName(const string& name) const; + // Nested type stuff ----------------------------------------------- // The number of nested types in this message type. @@ -217,6 +249,9 @@ class LIBPROTOBUF_EXPORT Descriptor { // Returns true if the number is in one of the extension ranges. bool IsExtensionNumber(int number) const; + // Returns NULL if no extension range contains the given number. + const ExtensionRange* FindExtensionRangeContainingNumber(int number) const; + // The number of extensions -- extending *other* messages -- that were // defined nested within this message type's scope. int extension_count() const; @@ -236,6 +271,13 @@ class LIBPROTOBUF_EXPORT Descriptor { // this message type's scope. const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const; + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this message declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + private: typedef MessageOptions OptionsType; @@ -243,6 +285,10 @@ class LIBPROTOBUF_EXPORT Descriptor { // correct depth void DebugString(int depth, string *contents) const; + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector* output) const; + const string* name_; const string* full_name_; const FileDescriptor* file_; @@ -256,6 +302,8 @@ class LIBPROTOBUF_EXPORT Descriptor { int field_count_; FieldDescriptor* fields_; + int oneof_decl_count_; + OneofDescriptor* oneof_decls_; int nested_type_count_; Descriptor* nested_types_; int enum_type_count_; @@ -273,6 +321,7 @@ class LIBPROTOBUF_EXPORT Descriptor { friend class DescriptorBuilder; friend class EnumDescriptor; friend class FieldDescriptor; + friend class OneofDescriptor; friend class MethodDescriptor; friend class FileDescriptor; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Descriptor); @@ -388,15 +437,19 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // when parsing formats which prefer to use camel-case naming style. const string& camelcase_name() const; - Type type() const; // Declared type of this field. - CppType cpp_type() const; // C++ type of this field. - Label label() const; // optional/required/repeated + Type type() const; // Declared type of this field. + const char* type_name() const; // Name of the declared type. + CppType cpp_type() const; // C++ type of this field. + const char* cpp_type_name() const; // Name of the C++ type. + Label label() const; // optional/required/repeated bool is_required() const; // shorthand for label() == LABEL_REQUIRED bool is_optional() const; // shorthand for label() == LABEL_OPTIONAL bool is_repeated() const; // shorthand for label() == LABEL_REPEATED bool is_packable() const; // shorthand for is_repeated() && // IsTypePackable(type()) + bool is_packed() const; // shorthand for is_packable() && + // options().packed() // Index of this field within the message's field array, or the file or // extension scope's extensions array. @@ -439,6 +492,13 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // this is the extended type. Never NULL. const Descriptor* containing_type() const; + // If the field is a member of a oneof, this is the one, otherwise this is + // NULL. + const OneofDescriptor* containing_oneof() const; + + // If the field is a member of a oneof, returns the index in that oneof. + int index_in_oneof() const; + // An extension may be declared within the scope of another message. If this // field is an extension (is_extension() is true), then extension_scope() // returns that message, or NULL if the extension was declared at global @@ -447,10 +507,10 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { const Descriptor* extension_scope() const; // If type is TYPE_MESSAGE or TYPE_GROUP, returns a descriptor for the - // message or the group type. Otherwise, undefined. + // message or the group type. Otherwise, returns null. const Descriptor* message_type() const; // If type is TYPE_ENUM, returns a descriptor for the enum. Otherwise, - // undefined. + // returns null. const EnumDescriptor* enum_type() const; // EXPERIMENTAL; DO NOT USE. @@ -476,20 +536,39 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // Helper method to get the CppType for a particular Type. static CppType TypeToCppType(Type type); + // Helper method to get the name of a Type. + static const char* TypeName(Type type); + + // Helper method to get the name of a CppType. + static const char* CppTypeName(CppType cpp_type); + // Return true iff [packed = true] is valid for fields of this type. static inline bool IsTypePackable(Type field_type); + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this field declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + private: typedef FieldOptions OptionsType; // See Descriptor::DebugString(). - void DebugString(int depth, string *contents) const; + enum PrintLabelFlag { PRINT_LABEL, OMIT_LABEL }; + void DebugString(int depth, PrintLabelFlag print_label_flag, + string* contents) const; // formats the default value appropriately and returns it as a string. // Must have a default value to call this. If quote_string_type is true, then // types of CPPTYPE_STRING whill be surrounded by quotes and CEscaped. string DefaultValueAsString(bool quote_string_type) const; + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector* output) const; + const string* name_; const string* full_name_; const string* lowercase_name_; @@ -499,7 +578,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { Type type_; Label label_; bool is_extension_; + int index_in_oneof_; const Descriptor* containing_type_; + const OneofDescriptor* containing_oneof_; const Descriptor* extension_scope_; const Descriptor* message_type_; const EnumDescriptor* enum_type_; @@ -527,6 +608,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { static const char * const kTypeToName[MAX_TYPE + 1]; + static const char * const kCppTypeToName[MAX_CPPTYPE + 1]; + static const char * const kLabelToName[MAX_LABEL + 1]; // Must be constructed using DescriptorPool. @@ -534,9 +617,66 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { friend class DescriptorBuilder; friend class FileDescriptor; friend class Descriptor; + friend class OneofDescriptor; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldDescriptor); }; +// Describes a oneof defined in a message type. +class LIBPROTOBUF_EXPORT OneofDescriptor { + public: + const string& name() const; // Name of this oneof. + const string& full_name() const; // Fully-qualified name of the oneof. + + // Index of this oneof within the message's oneof array. + int index() const; + + // The Descriptor for the message containing this oneof. + const Descriptor* containing_type() const; + + // The number of (non-extension) fields which are members of this oneof. + int field_count() const; + // Get a member of this oneof, in the order in which they were declared in the + // .proto file. Does not include extensions. + const FieldDescriptor* field(int index) const; + + // See Descriptor::CopyTo(). + void CopyTo(OneofDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + string DebugString() const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this oneof declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + // See Descriptor::DebugString(). + void DebugString(int depth, string* contents) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector* output) const; + + const string* name_; + const string* full_name_; + const Descriptor* containing_type_; + bool is_extendable_; + int field_count_; + const FieldDescriptor** fields_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate() and AllocateArray() + // in descriptor.cc and update them to initialize the field. + + // Must be constructed using DescriptorPool. + OneofDescriptor() {} + friend class DescriptorBuilder; + friend class Descriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofDescriptor); +}; + // Describes an enum type defined in a .proto file. To get the EnumDescriptor // for a generated enum type, call TypeName_descriptor(). Use DescriptorPool // to construct your own descriptors. @@ -583,12 +723,28 @@ class LIBPROTOBUF_EXPORT EnumDescriptor { // See Descriptor::DebugString(). string DebugString() const; + // Returns true if this is a placeholder for an unknown enum. This will + // only be the case if this descriptor comes from a DescriptorPool + // with AllowUnknownDependencies() set. + bool is_placeholder() const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this enum declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + private: typedef EnumOptions OptionsType; // See Descriptor::DebugString(). void DebugString(int depth, string *contents) const; + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector* output) const; + const string* name_; const string* full_name_; const FileDescriptor* file_; @@ -650,12 +806,23 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor { // See Descriptor::DebugString(). string DebugString() const; + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this enum value declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + private: typedef EnumValueOptions OptionsType; // See Descriptor::DebugString(). void DebugString(int depth, string *contents) const; + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector* output) const; + const string* name_; const string* full_name_; int number_; @@ -703,19 +870,29 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor { // Look up a MethodDescriptor by name. const MethodDescriptor* FindMethodByName(const string& name) const; - // See Descriptor::CopyTo(). void CopyTo(ServiceDescriptorProto* proto) const; // See Descriptor::DebugString(). string DebugString() const; + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this service declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + private: typedef ServiceOptions OptionsType; // See Descriptor::DebugString(). void DebugString(string *contents) const; + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector* output) const; + const string* name_; const string* full_name_; const FileDescriptor* file_; @@ -768,12 +945,23 @@ class LIBPROTOBUF_EXPORT MethodDescriptor { // See Descriptor::DebugString(). string DebugString() const; + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this method declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + private: typedef MethodOptions OptionsType; // See Descriptor::DebugString(). void DebugString(int depth, string *contents) const; + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector* output) const; + const string* name_; const string* full_name_; const ServiceDescriptor* service_; @@ -791,6 +979,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptor { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MethodDescriptor); }; + // Describes a whole .proto file. To get the FileDescriptor for a compiled-in // file, get the descriptor for something defined in that file and call // descriptor->file(). Use DescriptorPool to construct your own descriptors. @@ -813,6 +1002,22 @@ class LIBPROTOBUF_EXPORT FileDescriptor { // These are returned in the order they were defined in the .proto file. const FileDescriptor* dependency(int index) const; + // The number of files public imported by this one. + // The public dependency list is a subset of the dependency list. + int public_dependency_count() const; + // Gets a public imported file by index, where 0 <= index < + // public_dependency_count(). + // These are returned in the order they were defined in the .proto file. + const FileDescriptor* public_dependency(int index) const; + + // The number of files that are imported for weak fields. + // The weak dependency list is a subset of the dependency list. + int weak_dependency_count() const; + // Gets a weak imported file by index, where 0 <= index < + // weak_dependency_count(). + // These are returned in the order they were defined in the .proto file. + const FileDescriptor* weak_dependency(int index) const; + // Number of top-level message types defined in this file. (This does not // include nested types.) int message_type_count() const; @@ -866,12 +1071,33 @@ class LIBPROTOBUF_EXPORT FileDescriptor { const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const; // See Descriptor::CopyTo(). + // Notes: + // - This method does NOT copy source code information since it is relatively + // large and rarely needed. See CopySourceCodeInfoTo() below. void CopyTo(FileDescriptorProto* proto) const; + // Write the source code information of this FileDescriptor into the given + // FileDescriptorProto. See CopyTo() above. + void CopySourceCodeInfoTo(FileDescriptorProto* proto) const; // See Descriptor::DebugString(). string DebugString() const; + // Returns true if this is a placeholder for an unknown file. This will + // only be the case if this descriptor comes from a DescriptorPool + // with AllowUnknownDependencies() set. + bool is_placeholder() const; + private: + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of the declaration or declaration-part denoted by |path|. + // Returns false and leaves |*out_location| unchanged iff location + // information was not available. (See SourceCodeInfo for + // description of path encoding.) + bool GetSourceLocation(const std::vector& path, + SourceLocation* out_location) const; + typedef FileOptions OptionsType; const string* name_; @@ -879,6 +1105,10 @@ class LIBPROTOBUF_EXPORT FileDescriptor { const DescriptorPool* pool_; int dependency_count_; const FileDescriptor** dependencies_; + int public_dependency_count_; + int* public_dependencies_; + int weak_dependency_count_; + int* weak_dependencies_; int message_type_count_; Descriptor* message_types_; int enum_type_count_; @@ -886,10 +1116,12 @@ class LIBPROTOBUF_EXPORT FileDescriptor { int service_count_; ServiceDescriptor* services_; int extension_count_; + bool is_placeholder_; FieldDescriptor* extensions_; const FileOptions* options_; const FileDescriptorTables* tables_; + const SourceCodeInfo* source_code_info_; // IMPORTANT: If you add a new field, make sure to search for all instances // of Allocate() and AllocateArray() in // descriptor.cc and update them to initialize the field. @@ -898,7 +1130,10 @@ class LIBPROTOBUF_EXPORT FileDescriptor { friend class DescriptorBuilder; friend class Descriptor; friend class FieldDescriptor; + friend class OneofDescriptor; friend class EnumDescriptor; + friend class EnumValueDescriptor; + friend class MethodDescriptor; friend class ServiceDescriptor; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileDescriptor); }; @@ -953,6 +1188,10 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // to GOOGLE_LOG(ERROR). Remember that files are built on-demand, so this // ErrorCollector may be called from any thread that calls one of the // Find*By*() methods. + // - The DescriptorDatabase must not be mutated during the lifetime of + // the DescriptorPool. Even if the client takes care to avoid data races, + // changes to the content of the DescriptorDatabase may not be reflected + // in subsequent lookups in the DescriptorPool. class ErrorCollector; explicit DescriptorPool(DescriptorDatabase* fallback_database, ErrorCollector* error_collector = NULL); @@ -983,6 +1222,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool { const Descriptor* FindMessageTypeByName(const string& name) const; const FieldDescriptor* FindFieldByName(const string& name) const; const FieldDescriptor* FindExtensionByName(const string& name) const; + const OneofDescriptor* FindOneofByName(const string& name) const; const EnumDescriptor* FindEnumTypeByName(const string& name) const; const EnumValueDescriptor* FindEnumValueByName(const string& name) const; const ServiceDescriptor* FindServiceByName(const string& name) const; @@ -999,7 +1239,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // found: extensions defined in the fallback database might not be found // depending on the database implementation. void FindAllExtensions(const Descriptor* extendee, - vector* out) const; + std::vector* out) const; // Building descriptors -------------------------------------------- @@ -1027,7 +1267,8 @@ class LIBPROTOBUF_EXPORT DescriptorPool { OTHER // some other problem }; - // Reports an error in the FileDescriptorProto. + // Reports an error in the FileDescriptorProto. Use this function if the + // problem occured should interrupt building the FileDescriptorProto. virtual void AddError( const string& filename, // File name in which the error occurred. const string& element_name, // Full name of the erroneous element. @@ -1036,6 +1277,16 @@ class LIBPROTOBUF_EXPORT DescriptorPool { const string& message // Human-readable error message. ) = 0; + // Reports a warning in the FileDescriptorProto. Use this function if the + // problem occured should NOT interrupt building the FileDescriptorProto. + virtual void AddWarning( + const string& filename, // File name in which the error occurred. + const string& element_name, // Full name of the erroneous element. + const Message* descriptor, // Descriptor of the erroneous element. + ErrorLocation location, // One of the location constants, above. + const string& message // Human-readable error message. + ) {} + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector); }; @@ -1056,7 +1307,8 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // to types or other files that are not found in the DescriptorPool (or its // backing DescriptorDatabase, if any). If you call // AllowUnknownDependencies(), however, then unknown types and files - // will be replaced by placeholder descriptors. This can allow you to + // will be replaced by placeholder descriptors (which can be identified by + // the is_placeholder() method). This can allow you to // perform some useful operations with a .proto file even if you do not // have access to other .proto files on which it depends. However, some // heuristics must be used to fill in the gaps in information, and these @@ -1065,10 +1317,15 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // or an enum, as well as what package it resides in. Furthermore, // placeholder types will not be discoverable via FindMessageTypeByName() // and similar methods, which could confuse some descriptor-based algorithms. - // Generally, the results of this option should only be relied upon for - // debugging purposes. + // Generally, the results of this option should be handled with extreme care. void AllowUnknownDependencies() { allow_unknown_ = true; } + // By default, weak imports are allowed to be missing, in which case we will + // use a placeholder for the dependency and convert the field to be an Empty + // message field. If you call EnforceWeakDependencies(true), however, the + // DescriptorPool will report a import not found error. + void EnforceWeakDependencies(bool enforce) { enforce_weak_ = enforce; } + // Internal stuff -------------------------------------------------- // These methods MUST NOT be called from outside the proto2 library. // These methods may contain hidden pitfalls and may be removed in a @@ -1106,7 +1363,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // For internal use only: Gets a non-const pointer to the generated pool. // This is called at static-initialization time only, so thread-safety is // not a concern. If both an underlay and a fallback database are present, - // the fallback database takes precedence. + // the underlay takes precedence. static DescriptorPool* internal_generated_pool(); // For internal use only: Changes the behavior of BuildFile() such that it @@ -1124,6 +1381,12 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // lazy descriptor initialization behavior. bool InternalIsFileLoaded(const string& filename) const; + + // Add a file to unused_import_track_files_. DescriptorBuilder will log + // warnings for those files if there is any unused import. + void AddUnusedImportTrackFile(const string& file_name); + void ClearUnusedImportTrackFiles(); + private: friend class Descriptor; friend class FieldDescriptor; @@ -1132,6 +1395,11 @@ class LIBPROTOBUF_EXPORT DescriptorPool { friend class FileDescriptor; friend class DescriptorBuilder; + // Return true if the given name is a sub-symbol of any non-package + // descriptor that already exists in the descriptor pool. (The full + // definition of such types is already known.) + bool IsSubSymbolOfBuiltType(const string& name) const; + // Tries to find something in the fallback database and link in the // corresponding proto file. Returns true if successful, in which case // the caller should search for the thing again. These are declared @@ -1163,6 +1431,8 @@ class LIBPROTOBUF_EXPORT DescriptorPool { bool enforce_dependencies_; bool allow_unknown_; + bool enforce_weak_; + std::set unused_import_track_files_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPool); }; @@ -1190,10 +1460,12 @@ PROTOBUF_DEFINE_ACCESSOR(Descriptor, file, const FileDescriptor*) PROTOBUF_DEFINE_ACCESSOR(Descriptor, containing_type, const Descriptor*) PROTOBUF_DEFINE_ACCESSOR(Descriptor, field_count, int) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, oneof_decl_count, int) PROTOBUF_DEFINE_ACCESSOR(Descriptor, nested_type_count, int) PROTOBUF_DEFINE_ACCESSOR(Descriptor, enum_type_count, int) PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, field, const FieldDescriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, oneof_decl, const OneofDescriptor*) PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, nested_type, const Descriptor*) PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, enum_type, const EnumDescriptor*) @@ -1204,6 +1476,7 @@ PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension_range, PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension, const FieldDescriptor*) PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions); +PROTOBUF_DEFINE_ACCESSOR(Descriptor, is_placeholder, bool) PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, name) PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, full_name) @@ -1215,12 +1488,15 @@ PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, is_extension, bool) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, type, FieldDescriptor::Type) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, label, FieldDescriptor::Label) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, containing_type, const Descriptor*) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, containing_oneof, + const OneofDescriptor*) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, index_in_oneof, int) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, extension_scope, const Descriptor*) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, message_type, const Descriptor*) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, enum_type, const EnumDescriptor*) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, experimental_map_key, const FieldDescriptor*) -PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FieldDescriptor, FieldOptions); +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FieldDescriptor, FieldOptions) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, has_default_value, bool) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int32 , int32 ) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int64 , int64 ) @@ -1233,6 +1509,11 @@ PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_enum, const EnumValueDescriptor*) PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, default_value_string) +PROTOBUF_DEFINE_STRING_ACCESSOR(OneofDescriptor, name) +PROTOBUF_DEFINE_STRING_ACCESSOR(OneofDescriptor, full_name) +PROTOBUF_DEFINE_ACCESSOR(OneofDescriptor, containing_type, const Descriptor*) +PROTOBUF_DEFINE_ACCESSOR(OneofDescriptor, field_count, int) + PROTOBUF_DEFINE_STRING_ACCESSOR(EnumDescriptor, name) PROTOBUF_DEFINE_STRING_ACCESSOR(EnumDescriptor, full_name) PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, file, const FileDescriptor*) @@ -1241,12 +1522,13 @@ PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, value_count, int) PROTOBUF_DEFINE_ARRAY_ACCESSOR(EnumDescriptor, value, const EnumValueDescriptor*) PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumDescriptor, EnumOptions); +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, is_placeholder, bool) PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, name) PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, full_name) PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, number, int) PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, type, const EnumDescriptor*) -PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumValueDescriptor, EnumValueOptions); +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumValueDescriptor, EnumValueOptions) PROTOBUF_DEFINE_STRING_ACCESSOR(ServiceDescriptor, name) PROTOBUF_DEFINE_STRING_ACCESSOR(ServiceDescriptor, full_name) @@ -1262,16 +1544,18 @@ PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, service, const ServiceDescriptor*) PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, input_type, const Descriptor*) PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, output_type, const Descriptor*) PROTOBUF_DEFINE_OPTIONS_ACCESSOR(MethodDescriptor, MethodOptions); - PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, name) PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, package) PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, pool, const DescriptorPool*) PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, dependency_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, public_dependency_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, weak_dependency_count, int) PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, message_type_count, int) PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, enum_type_count, int) PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, service_count, int) PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, extension_count, int) PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FileDescriptor, FileOptions); +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, is_placeholder, bool) PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, message_type, const Descriptor*) PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, enum_type, const EnumDescriptor*) @@ -1286,6 +1570,10 @@ PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, extension, // A few accessors differ from the macros... +inline bool Descriptor::IsExtensionNumber(int number) const { + return FindExtensionRangeContainingNumber(number) != NULL; +} + inline bool FieldDescriptor::is_required() const { return label() == LABEL_REQUIRED; } @@ -1322,6 +1610,10 @@ inline int Descriptor::index() const { } } +inline int OneofDescriptor::index() const { + return this - containing_type_->oneof_decls_; +} + inline int EnumDescriptor::index() const { if (containing_type_ == NULL) { return this - file_->enum_types_; @@ -1342,14 +1634,30 @@ inline int MethodDescriptor::index() const { return this - service_->methods_; } +inline const char* FieldDescriptor::type_name() const { + return kTypeToName[type_]; +} + inline FieldDescriptor::CppType FieldDescriptor::cpp_type() const { return kTypeToCppTypeMap[type_]; } +inline const char* FieldDescriptor::cpp_type_name() const { + return kCppTypeToName[kTypeToCppTypeMap[type_]]; +} + inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) { return kTypeToCppTypeMap[type]; } +inline const char* FieldDescriptor::TypeName(Type type) { + return kTypeToName[type]; +} + +inline const char* FieldDescriptor::CppTypeName(CppType cpp_type) { + return kCppTypeToName[cpp_type]; +} + inline bool FieldDescriptor::IsTypePackable(Type field_type) { return (field_type != FieldDescriptor::TYPE_STRING && field_type != FieldDescriptor::TYPE_GROUP && @@ -1361,6 +1669,22 @@ inline const FileDescriptor* FileDescriptor::dependency(int index) const { return dependencies_[index]; } +inline const FileDescriptor* FileDescriptor::public_dependency( + int index) const { + return dependencies_[public_dependencies_[index]]; +} + +inline const FileDescriptor* FileDescriptor::weak_dependency( + int index) const { + return dependencies_[weak_dependencies_[index]]; +} + +// Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because fields_ is actually an array +// of pointers rather than the usual array of objects. +inline const FieldDescriptor* OneofDescriptor::field(int index) const { + return fields_[index]; +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index f61e7cd..c3aa2fb 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -1,11 +1,17 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/descriptor.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include "google/protobuf/descriptor.pb.h" + +#include + +#include #include #include #include #include +#include #include #include // @@protoc_insertion_point(includes) @@ -32,6 +38,9 @@ const ::google::protobuf::internal::GeneratedMessageReflection* FieldDescriptorProto_reflection_ = NULL; const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor_ = NULL; const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor_ = NULL; +const ::google::protobuf::Descriptor* OneofDescriptorProto_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + OneofDescriptorProto_reflection_ = NULL; const ::google::protobuf::Descriptor* EnumDescriptorProto_descriptor_ = NULL; const ::google::protobuf::internal::GeneratedMessageReflection* EnumDescriptorProto_reflection_ = NULL; @@ -73,6 +82,12 @@ const ::google::protobuf::internal::GeneratedMessageReflection* const ::google::protobuf::Descriptor* UninterpretedOption_NamePart_descriptor_ = NULL; const ::google::protobuf::internal::GeneratedMessageReflection* UninterpretedOption_NamePart_reflection_ = NULL; +const ::google::protobuf::Descriptor* SourceCodeInfo_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + SourceCodeInfo_reflection_ = NULL; +const ::google::protobuf::Descriptor* SourceCodeInfo_Location_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + SourceCodeInfo_Location_reflection_ = NULL; } // namespace @@ -99,15 +114,18 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::MessageFactory::generated_factory(), sizeof(FileDescriptorSet)); FileDescriptorProto_descriptor_ = file->message_type(1); - static const int FileDescriptorProto_offsets_[8] = { + static const int FileDescriptorProto_offsets_[11] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, package_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, dependency_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, public_dependency_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, weak_dependency_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, message_type_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, enum_type_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, service_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, extension_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, options_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, source_code_info_), }; FileDescriptorProto_reflection_ = new ::google::protobuf::internal::GeneratedMessageReflection( @@ -121,13 +139,14 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::MessageFactory::generated_factory(), sizeof(FileDescriptorProto)); DescriptorProto_descriptor_ = file->message_type(2); - static const int DescriptorProto_offsets_[7] = { + static const int DescriptorProto_offsets_[8] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, field_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, nested_type_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, enum_type_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_range_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, oneof_decl_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, options_), }; DescriptorProto_reflection_ = @@ -158,7 +177,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::MessageFactory::generated_factory(), sizeof(DescriptorProto_ExtensionRange)); FieldDescriptorProto_descriptor_ = file->message_type(3); - static const int FieldDescriptorProto_offsets_[8] = { + static const int FieldDescriptorProto_offsets_[9] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, number_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, label_), @@ -166,6 +185,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, type_name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, extendee_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, default_value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, oneof_index_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, options_), }; FieldDescriptorProto_reflection_ = @@ -181,7 +201,22 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { sizeof(FieldDescriptorProto)); FieldDescriptorProto_Type_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(0); FieldDescriptorProto_Label_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(1); - EnumDescriptorProto_descriptor_ = file->message_type(4); + OneofDescriptorProto_descriptor_ = file->message_type(4); + static const int OneofDescriptorProto_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, name_), + }; + OneofDescriptorProto_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + OneofDescriptorProto_descriptor_, + OneofDescriptorProto::default_instance_, + OneofDescriptorProto_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(OneofDescriptorProto)); + EnumDescriptorProto_descriptor_ = file->message_type(5); static const int EnumDescriptorProto_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, value_), @@ -198,7 +233,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(EnumDescriptorProto)); - EnumValueDescriptorProto_descriptor_ = file->message_type(5); + EnumValueDescriptorProto_descriptor_ = file->message_type(6); static const int EnumValueDescriptorProto_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, number_), @@ -215,7 +250,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(EnumValueDescriptorProto)); - ServiceDescriptorProto_descriptor_ = file->message_type(6); + ServiceDescriptorProto_descriptor_ = file->message_type(7); static const int ServiceDescriptorProto_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, method_), @@ -232,7 +267,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(ServiceDescriptorProto)); - MethodDescriptorProto_descriptor_ = file->message_type(7); + MethodDescriptorProto_descriptor_ = file->message_type(8); static const int MethodDescriptorProto_offsets_[4] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, input_type_), @@ -250,15 +285,19 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(MethodDescriptorProto)); - FileOptions_descriptor_ = file->message_type(8); - static const int FileOptions_offsets_[8] = { + FileOptions_descriptor_ = file->message_type(9); + static const int FileOptions_offsets_[12] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generate_equals_and_hash_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_string_check_utf8_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, optimize_for_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, go_package_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_), }; FileOptions_reflection_ = @@ -273,10 +312,11 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::MessageFactory::generated_factory(), sizeof(FileOptions)); FileOptions_OptimizeMode_descriptor_ = FileOptions_descriptor_->enum_type(0); - MessageOptions_descriptor_ = file->message_type(9); - static const int MessageOptions_offsets_[3] = { + MessageOptions_descriptor_ = file->message_type(10); + static const int MessageOptions_offsets_[4] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, message_set_wire_format_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, no_standard_descriptor_accessor_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, uninterpreted_option_), }; MessageOptions_reflection_ = @@ -290,12 +330,14 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(MessageOptions)); - FieldOptions_descriptor_ = file->message_type(10); - static const int FieldOptions_offsets_[5] = { + FieldOptions_descriptor_ = file->message_type(11); + static const int FieldOptions_offsets_[7] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, lazy_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, experimental_map_key_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, weak_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, uninterpreted_option_), }; FieldOptions_reflection_ = @@ -310,8 +352,10 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::MessageFactory::generated_factory(), sizeof(FieldOptions)); FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0); - EnumOptions_descriptor_ = file->message_type(11); - static const int EnumOptions_offsets_[1] = { + EnumOptions_descriptor_ = file->message_type(12); + static const int EnumOptions_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, allow_alias_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, uninterpreted_option_), }; EnumOptions_reflection_ = @@ -325,8 +369,9 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(EnumOptions)); - EnumValueOptions_descriptor_ = file->message_type(12); - static const int EnumValueOptions_offsets_[1] = { + EnumValueOptions_descriptor_ = file->message_type(13); + static const int EnumValueOptions_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, uninterpreted_option_), }; EnumValueOptions_reflection_ = @@ -340,8 +385,9 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(EnumValueOptions)); - ServiceOptions_descriptor_ = file->message_type(13); - static const int ServiceOptions_offsets_[1] = { + ServiceOptions_descriptor_ = file->message_type(14); + static const int ServiceOptions_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, uninterpreted_option_), }; ServiceOptions_reflection_ = @@ -355,8 +401,9 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(ServiceOptions)); - MethodOptions_descriptor_ = file->message_type(14); - static const int MethodOptions_offsets_[1] = { + MethodOptions_descriptor_ = file->message_type(15); + static const int MethodOptions_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, uninterpreted_option_), }; MethodOptions_reflection_ = @@ -370,14 +417,15 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(MethodOptions)); - UninterpretedOption_descriptor_ = file->message_type(15); - static const int UninterpretedOption_offsets_[6] = { + UninterpretedOption_descriptor_ = file->message_type(16); + static const int UninterpretedOption_offsets_[7] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, identifier_value_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, positive_int_value_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, negative_int_value_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, double_value_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, string_value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, aggregate_value_), }; UninterpretedOption_reflection_ = new ::google::protobuf::internal::GeneratedMessageReflection( @@ -406,6 +454,39 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(UninterpretedOption_NamePart)); + SourceCodeInfo_descriptor_ = file->message_type(17); + static const int SourceCodeInfo_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, location_), + }; + SourceCodeInfo_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + SourceCodeInfo_descriptor_, + SourceCodeInfo::default_instance_, + SourceCodeInfo_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(SourceCodeInfo)); + SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0); + static const int SourceCodeInfo_Location_offsets_[4] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_comments_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, trailing_comments_), + }; + SourceCodeInfo_Location_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + SourceCodeInfo_Location_descriptor_, + SourceCodeInfo_Location::default_instance_, + SourceCodeInfo_Location_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(SourceCodeInfo_Location)); } namespace { @@ -429,6 +510,8 @@ void protobuf_RegisterTypes(const ::std::string&) { ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( FieldDescriptorProto_descriptor_, &FieldDescriptorProto::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + OneofDescriptorProto_descriptor_, &OneofDescriptorProto::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( EnumDescriptorProto_descriptor_, &EnumDescriptorProto::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( EnumValueDescriptorProto_descriptor_, &EnumValueDescriptorProto::default_instance()); @@ -454,6 +537,10 @@ void protobuf_RegisterTypes(const ::std::string&) { UninterpretedOption_descriptor_, &UninterpretedOption::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( UninterpretedOption_NamePart_descriptor_, &UninterpretedOption_NamePart::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + SourceCodeInfo_descriptor_, &SourceCodeInfo::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + SourceCodeInfo_Location_descriptor_, &SourceCodeInfo_Location::default_instance()); } } // namespace @@ -469,6 +556,8 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() { delete DescriptorProto_ExtensionRange_reflection_; delete FieldDescriptorProto::default_instance_; delete FieldDescriptorProto_reflection_; + delete OneofDescriptorProto::default_instance_; + delete OneofDescriptorProto_reflection_; delete EnumDescriptorProto::default_instance_; delete EnumDescriptorProto_reflection_; delete EnumValueDescriptorProto::default_instance_; @@ -495,6 +584,10 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() { delete UninterpretedOption_reflection_; delete UninterpretedOption_NamePart::default_instance_; delete UninterpretedOption_NamePart_reflection_; + delete SourceCodeInfo::default_instance_; + delete SourceCodeInfo_reflection_; + delete SourceCodeInfo_Location::default_instance_; + delete SourceCodeInfo_Location_reflection_; } void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { @@ -507,96 +600,115 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "\n google/protobuf/descriptor.proto\022\017goog" "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file" "\030\001 \003(\0132$.google.protobuf.FileDescriptorP" - "roto\"\334\002\n\023FileDescriptorProto\022\014\n\004name\030\001 \001" + "roto\"\313\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001" "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022" - "6\n\014message_type\030\004 \003(\0132 .google.protobuf." - "DescriptorProto\0227\n\tenum_type\030\005 \003(\0132$.goo" - "gle.protobuf.EnumDescriptorProto\0228\n\007serv" - "ice\030\006 \003(\0132\'.google.protobuf.ServiceDescr" - "iptorProto\0228\n\textension\030\007 \003(\0132%.google.p" - "rotobuf.FieldDescriptorProto\022-\n\007options\030" - "\010 \001(\0132\034.google.protobuf.FileOptions\"\251\003\n\017" - "DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005field\030\002" - " \003(\0132%.google.protobuf.FieldDescriptorPr" - "oto\0228\n\textension\030\006 \003(\0132%.google.protobuf" - ".FieldDescriptorProto\0225\n\013nested_type\030\003 \003" - "(\0132 .google.protobuf.DescriptorProto\0227\n\t" - "enum_type\030\004 \003(\0132$.google.protobuf.EnumDe" - "scriptorProto\022H\n\017extension_range\030\005 \003(\0132/" - ".google.protobuf.DescriptorProto.Extensi" - "onRange\0220\n\007options\030\007 \001(\0132\037.google.protob" - "uf.MessageOptions\032,\n\016ExtensionRange\022\r\n\005s" - "tart\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\224\005\n\024FieldDescrip" - "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:" - "\n\005label\030\004 \001(\0162+.google.protobuf.FieldDes" - "criptorProto.Label\0228\n\004type\030\005 \001(\0162*.googl" - "e.protobuf.FieldDescriptorProto.Type\022\021\n\t" - "type_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdef" - "ault_value\030\007 \001(\t\022.\n\007options\030\010 \001(\0132\035.goog" - "le.protobuf.FieldOptions\"\266\002\n\004Type\022\017\n\013TYP" - "E_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64" - "\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014T" - "YPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_" - "BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022" - "\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYP" - "E_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED" - "32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021" - "\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTI" - "ONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPE" - "ATED\020\003\"\214\001\n\023EnumDescriptorProto\022\014\n\004name\030\001" - " \001(\t\0228\n\005value\030\002 \003(\0132).google.protobuf.En" - "umValueDescriptorProto\022-\n\007options\030\003 \001(\0132" - "\034.google.protobuf.EnumOptions\"l\n\030EnumVal" - "ueDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006numbe" - "r\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.google.protob" - "uf.EnumValueOptions\"\220\001\n\026ServiceDescripto" - "rProto\022\014\n\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.g" - "oogle.protobuf.MethodDescriptorProto\0220\n\007" - "options\030\003 \001(\0132\037.google.protobuf.ServiceO" - "ptions\"\177\n\025MethodDescriptorProto\022\014\n\004name\030" - "\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013output_type" - "\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.protobu" - "f.MethodOptions\"\244\003\n\013FileOptions\022\024\n\014java_" - "package\030\001 \001(\t\022\034\n\024java_outer_classname\030\010 " - "\001(\t\022\"\n\023java_multiple_files\030\n \001(\010:\005false\022" - "F\n\014optimize_for\030\t \001(\0162).google.protobuf." - "FileOptions.OptimizeMode:\005SPEED\022!\n\023cc_ge" - "neric_services\030\020 \001(\010:\004true\022#\n\025java_gener" - "ic_services\030\021 \001(\010:\004true\022!\n\023py_generic_se" - "rvices\030\022 \001(\010:\004true\022C\n\024uninterpreted_opti" - "on\030\347\007 \003(\0132$.google.protobuf.Uninterprete" - "dOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCO" - "DE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270" - "\001\n\016MessageOptions\022&\n\027message_set_wire_fo" - "rmat\030\001 \001(\010:\005false\022.\n\037no_standard_descrip" - "tor_accessor\030\002 \001(\010:\005false\022C\n\024uninterpret" - "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint" - "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"\224\002\n\014FieldOptio" - "ns\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Fiel" - "dOptions.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\031" - "\n\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experimenta" - "l_map_key\030\t \001(\t\022C\n\024uninterpreted_option\030" - "\347\007 \003(\0132$.google.protobuf.UninterpretedOp" - "tion\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014S" - "TRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022" - "C\n\024uninterpreted_option\030\347\007 \003(\0132$.google." - "protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"" - "b\n\020EnumValueOptions\022C\n\024uninterpreted_opt" - "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret" - "edOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOptions\022C\n" - "\024uninterpreted_option\030\347\007 \003(\0132$.google.pr" - "otobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n" - "\rMethodOptions\022C\n\024uninterpreted_option\030\347" - "\007 \003(\0132$.google.protobuf.UninterpretedOpt" - "ion*\t\010\350\007\020\200\200\200\200\002\"\205\002\n\023UninterpretedOption\022;" - "\n\004name\030\002 \003(\0132-.google.protobuf.Uninterpr" - "etedOption.NamePart\022\030\n\020identifier_value\030" - "\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022neg" - "ative_int_value\030\005 \001(\003\022\024\n\014double_value\030\006 " - "\001(\001\022\024\n\014string_value\030\007 \001(\014\0323\n\010NamePart\022\021\n" - "\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010B)" - "\n\023com.google.protobufB\020DescriptorProtosH" - "\001", 3681); + "\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen" + "dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog" + "le.protobuf.DescriptorProto\0227\n\tenum_type" + "\030\005 \003(\0132$.google.protobuf.EnumDescriptorP" + "roto\0228\n\007service\030\006 \003(\0132\'.google.protobuf." + "ServiceDescriptorProto\0228\n\textension\030\007 \003(" + "\0132%.google.protobuf.FieldDescriptorProto" + "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File" + "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog" + "le.protobuf.SourceCodeInfo\"\344\003\n\017Descripto" + "rProto\022\014\n\004name\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.go" + "ogle.protobuf.FieldDescriptorProto\0228\n\tex" + "tension\030\006 \003(\0132%.google.protobuf.FieldDes" + "criptorProto\0225\n\013nested_type\030\003 \003(\0132 .goog" + "le.protobuf.DescriptorProto\0227\n\tenum_type" + "\030\004 \003(\0132$.google.protobuf.EnumDescriptorP" + "roto\022H\n\017extension_range\030\005 \003(\0132/.google.p" + "rotobuf.DescriptorProto.ExtensionRange\0229" + "\n\noneof_decl\030\010 \003(\0132%.google.protobuf.One" + "ofDescriptorProto\0220\n\007options\030\007 \001(\0132\037.goo" + "gle.protobuf.MessageOptions\032,\n\016Extension" + "Range\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\251\005\n\024Fi" + "eldDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006numb" + "er\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobu" + "f.FieldDescriptorProto.Label\0228\n\004type\030\005 \001" + "(\0162*.google.protobuf.FieldDescriptorProt" + "o.Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 " + "\001(\t\022\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_inde" + "x\030\t \001(\005\022.\n\007options\030\010 \001(\0132\035.google.protob" + "uf.FieldOptions\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020" + "\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYP" + "E_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED" + "64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n" + "\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_M" + "ESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020" + "\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rT" + "YPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_" + "SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n" + "\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"$\n" + "\024OneofDescriptorProto\022\014\n\004name\030\001 \001(\t\"\214\001\n\023" + "EnumDescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005val" + "ue\030\002 \003(\0132).google.protobuf.EnumValueDesc" + "riptorProto\022-\n\007options\030\003 \001(\0132\034.google.pr" + "otobuf.EnumOptions\"l\n\030EnumValueDescripto" + "rProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007" + "options\030\003 \001(\0132!.google.protobuf.EnumValu" + "eOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n\004n" + "ame\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.proto" + "buf.MethodDescriptorProto\0220\n\007options\030\003 \001" + "(\0132\037.google.protobuf.ServiceOptions\"\177\n\025M" + "ethodDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\nin" + "put_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007o" + "ptions\030\004 \001(\0132\036.google.protobuf.MethodOpt" + "ions\"\253\004\n\013FileOptions\022\024\n\014java_package\030\001 \001" + "(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023java" + "_multiple_files\030\n \001(\010:\005false\022,\n\035java_gen" + "erate_equals_and_hash\030\024 \001(\010:\005false\022%\n\026ja" + "va_string_check_utf8\030\033 \001(\010:\005false\022F\n\014opt" + "imize_for\030\t \001(\0162).google.protobuf.FileOp" + "tions.OptimizeMode:\005SPEED\022\022\n\ngo_package\030" + "\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005fals" + "e\022$\n\025java_generic_services\030\021 \001(\010:\005false\022" + "\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031\n\nd" + "eprecated\030\027 \001(\010:\005false\022C\n\024uninterpreted_" + "option\030\347\007 \003(\0132$.google.protobuf.Uninterp" + "retedOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r" + "\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200" + "\200\002\"\323\001\n\016MessageOptions\022&\n\027message_set_wir" + "e_format\030\001 \001(\010:\005false\022.\n\037no_standard_des" + "criptor_accessor\030\002 \001(\010:\005false\022\031\n\ndepreca" + "ted\030\003 \001(\010:\005false\022C\n\024uninterpreted_option" + "\030\347\007 \003(\0132$.google.protobuf.UninterpretedO" + "ption*\t\010\350\007\020\200\200\200\200\002\"\276\002\n\014FieldOptions\022:\n\005cty" + "pe\030\001 \001(\0162#.google.protobuf.FieldOptions." + "CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030\005 " + "\001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\034\n" + "\024experimental_map_key\030\t \001(\t\022\023\n\004weak\030\n \001(" + "\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132" + "$.google.protobuf.UninterpretedOption\"/\n" + "\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_P" + "IECE\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013all" + "ow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005fals" + "e\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl" + "e.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200" + "\002\"}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001(" + "\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132" + "$.google.protobuf.UninterpretedOption*\t\010" + "\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated" + "\030! \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007" + " \003(\0132$.google.protobuf.UninterpretedOpti" + "on*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndeprec" + "ated\030! \001(\010:\005false\022C\n\024uninterpreted_optio" + "n\030\347\007 \003(\0132$.google.protobuf.Uninterpreted" + "Option*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOptio" + "n\022;\n\004name\030\002 \003(\0132-.google.protobuf.Uninte" + "rpretedOption.NamePart\022\030\n\020identifier_val" + "ue\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022" + "negative_int_value\030\005 \001(\003\022\024\n\014double_value" + "\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregat" + "e_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001" + " \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\261\001\n\016SourceCod" + "eInfo\022:\n\010location\030\001 \003(\0132(.google.protobu" + "f.SourceCodeInfo.Location\032c\n\010Location\022\020\n" + "\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020lea" + "ding_comments\030\003 \001(\t\022\031\n\021trailing_comments" + "\030\004 \001(\tB)\n\023com.google.protobufB\020Descripto" + "rProtosH\001", 4449); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -604,6 +716,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { DescriptorProto::default_instance_ = new DescriptorProto(); DescriptorProto_ExtensionRange::default_instance_ = new DescriptorProto_ExtensionRange(); FieldDescriptorProto::default_instance_ = new FieldDescriptorProto(); + OneofDescriptorProto::default_instance_ = new OneofDescriptorProto(); EnumDescriptorProto::default_instance_ = new EnumDescriptorProto(); EnumValueDescriptorProto::default_instance_ = new EnumValueDescriptorProto(); ServiceDescriptorProto::default_instance_ = new ServiceDescriptorProto(); @@ -617,11 +730,14 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { MethodOptions::default_instance_ = new MethodOptions(); UninterpretedOption::default_instance_ = new UninterpretedOption(); UninterpretedOption_NamePart::default_instance_ = new UninterpretedOption_NamePart(); + SourceCodeInfo::default_instance_ = new SourceCodeInfo(); + SourceCodeInfo_Location::default_instance_ = new SourceCodeInfo_Location(); FileDescriptorSet::default_instance_->InitAsDefaultInstance(); FileDescriptorProto::default_instance_->InitAsDefaultInstance(); DescriptorProto::default_instance_->InitAsDefaultInstance(); DescriptorProto_ExtensionRange::default_instance_->InitAsDefaultInstance(); FieldDescriptorProto::default_instance_->InitAsDefaultInstance(); + OneofDescriptorProto::default_instance_->InitAsDefaultInstance(); EnumDescriptorProto::default_instance_->InitAsDefaultInstance(); EnumValueDescriptorProto::default_instance_->InitAsDefaultInstance(); ServiceDescriptorProto::default_instance_->InitAsDefaultInstance(); @@ -635,6 +751,8 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { MethodOptions::default_instance_->InitAsDefaultInstance(); UninterpretedOption::default_instance_->InitAsDefaultInstance(); UninterpretedOption_NamePart::default_instance_->InitAsDefaultInstance(); + SourceCodeInfo::default_instance_->InitAsDefaultInstance(); + SourceCodeInfo_Location::default_instance_->InitAsDefaultInstance(); ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto); } @@ -645,7 +763,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fdescriptor_2eproto { } } static_descriptor_initializer_google_2fprotobuf_2fdescriptor_2eproto_; - // =================================================================== #ifndef _MSC_VER @@ -655,6 +772,7 @@ const int FileDescriptorSet::kFileFieldNumber; FileDescriptorSet::FileDescriptorSet() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorSet) } void FileDescriptorSet::InitAsDefaultInstance() { @@ -664,6 +782,7 @@ FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorSet) } void FileDescriptorSet::SharedCtor() { @@ -672,6 +791,7 @@ void FileDescriptorSet::SharedCtor() { } FileDescriptorSet::~FileDescriptorSet() { + // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorSet) SharedDtor(); } @@ -691,7 +811,8 @@ const ::google::protobuf::Descriptor* FileDescriptorSet::descriptor() { } const FileDescriptorSet& FileDescriptorSet::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } FileDescriptorSet* FileDescriptorSet::default_instance_ = NULL; @@ -708,30 +829,34 @@ void FileDescriptorSet::Clear() { bool FileDescriptorSet::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.FileDescriptorSet) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated .google.protobuf.FileDescriptorProto file = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { parse_file: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_file())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(10)) goto parse_file; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -739,43 +864,52 @@ bool FileDescriptorSet::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.FileDescriptorSet) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.FileDescriptorSet) + return false; #undef DO_ } void FileDescriptorSet::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.FileDescriptorSet) // repeated .google.protobuf.FileDescriptorProto file = 1; for (int i = 0; i < this->file_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 1, this->file(i), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.FileDescriptorSet) } ::google::protobuf::uint8* FileDescriptorSet::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorSet) // repeated .google.protobuf.FileDescriptorProto file = 1; for (int i = 0; i < this->file_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 1, this->file(i), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorSet) return target; } int FileDescriptorSet::ByteSize() const { int total_size = 0; - + // repeated .google.protobuf.FileDescriptorProto file = 1; total_size += 1 * this->file_size(); for (int i = 0; i < this->file_size(); i++) { @@ -783,7 +917,7 @@ int FileDescriptorSet::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->file(i)); } - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -826,10 +960,8 @@ void FileDescriptorSet::CopyFrom(const FileDescriptorSet& from) { } bool FileDescriptorSet::IsInitialized() const { - - for (int i = 0; i < file_size(); i++) { - if (!this->file(i).IsInitialized()) return false; - } + + if (!::google::protobuf::internal::AllAreInitialized(this->file())) return false; return true; } @@ -853,55 +985,63 @@ void FileDescriptorSet::Swap(FileDescriptorSet* other) { // =================================================================== -const ::std::string FileDescriptorProto::_default_name_; -const ::std::string FileDescriptorProto::_default_package_; #ifndef _MSC_VER const int FileDescriptorProto::kNameFieldNumber; const int FileDescriptorProto::kPackageFieldNumber; const int FileDescriptorProto::kDependencyFieldNumber; +const int FileDescriptorProto::kPublicDependencyFieldNumber; +const int FileDescriptorProto::kWeakDependencyFieldNumber; const int FileDescriptorProto::kMessageTypeFieldNumber; const int FileDescriptorProto::kEnumTypeFieldNumber; const int FileDescriptorProto::kServiceFieldNumber; const int FileDescriptorProto::kExtensionFieldNumber; const int FileDescriptorProto::kOptionsFieldNumber; +const int FileDescriptorProto::kSourceCodeInfoFieldNumber; #endif // !_MSC_VER FileDescriptorProto::FileDescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorProto) } void FileDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::FileOptions*>(&::google::protobuf::FileOptions::default_instance()); + source_code_info_ = const_cast< ::google::protobuf::SourceCodeInfo*>(&::google::protobuf::SourceCodeInfo::default_instance()); } FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorProto) } void FileDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); - package_ = const_cast< ::std::string*>(&_default_package_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); options_ = NULL; + source_code_info_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } FileDescriptorProto::~FileDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorProto) SharedDtor(); } void FileDescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } - if (package_ != &_default_package_) { + if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete package_; } if (this != default_instance_) { delete options_; + delete source_code_info_; } } @@ -916,7 +1056,8 @@ const ::google::protobuf::Descriptor* FileDescriptorProto::descriptor() { } const FileDescriptorProto& FileDescriptorProto::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } FileDescriptorProto* FileDescriptorProto::default_instance_ = NULL; @@ -926,22 +1067,29 @@ FileDescriptorProto* FileDescriptorProto::New() const { } void FileDescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (_has_bits_[0 / 32] & 3) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } - if (_has_bit(1)) { - if (package_ != &_default_package_) { + if (has_package()) { + if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { package_->clear(); } } - if (_has_bit(7)) { + } + if (_has_bits_[8 / 32] & 1536) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); } + if (has_source_code_info()) { + if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear(); + } } dependency_.Clear(); + public_dependency_.Clear(); + weak_dependency_.Clear(); message_type_.Clear(); enum_type_.Clear(); service_.Clear(); @@ -952,140 +1100,192 @@ void FileDescriptorProto::Clear() { bool FileDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.FileDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_package; break; } - + // optional string package = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_package: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_package())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->package().data(), this->package().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "package"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(26)) goto parse_dependency; break; } - + // repeated string dependency = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_dependency: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->add_dependency())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( - this->dependency(0).data(), this->dependency(0).length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->dependency(this->dependency_size() - 1).data(), + this->dependency(this->dependency_size() - 1).length(), + ::google::protobuf::internal::WireFormat::PARSE, + "dependency"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(26)) goto parse_dependency; if (input->ExpectTag(34)) goto parse_message_type; break; } - + // repeated .google.protobuf.DescriptorProto message_type = 4; case 4: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 34) { parse_message_type: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_message_type())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(34)) goto parse_message_type; if (input->ExpectTag(42)) goto parse_enum_type; break; } - + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; case 5: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 42) { parse_enum_type: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_enum_type())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(42)) goto parse_enum_type; if (input->ExpectTag(50)) goto parse_service; break; } - + // repeated .google.protobuf.ServiceDescriptorProto service = 6; case 6: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 50) { parse_service: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_service())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(50)) goto parse_service; if (input->ExpectTag(58)) goto parse_extension; break; } - + // repeated .google.protobuf.FieldDescriptorProto extension = 7; case 7: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 58) { parse_extension: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_extension())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(58)) goto parse_extension; if (input->ExpectTag(66)) goto parse_options; break; } - + // optional .google.protobuf.FileOptions options = 8; case 8: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 66) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; + } + if (input->ExpectTag(74)) goto parse_source_code_info; + break; + } + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + case 9: { + if (tag == 74) { + parse_source_code_info: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_source_code_info())); + } else { + goto handle_unusual; + } + if (input->ExpectTag(80)) goto parse_public_dependency; + break; + } + + // repeated int32 public_dependency = 10; + case 10: { + if (tag == 80) { + parse_public_dependency: + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + 1, 80, input, this->mutable_public_dependency()))); + } else if (tag == 82) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, this->mutable_public_dependency()))); + } else { + goto handle_unusual; + } + if (input->ExpectTag(80)) goto parse_public_dependency; + if (input->ExpectTag(88)) goto parse_weak_dependency; + break; + } + + // repeated int32 weak_dependency = 11; + case 11: { + if (tag == 88) { + parse_weak_dependency: + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + 1, 88, input, this->mutable_weak_dependency()))); + } else if (tag == 90) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, this->mutable_weak_dependency()))); + } else { + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectTag(88)) goto parse_weak_dependency; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -1093,151 +1293,203 @@ bool FileDescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.FileDescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.FileDescriptorProto) + return false; #undef DO_ } void FileDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.FileDescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } - + // optional string package = 2; - if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_package()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->package().data(), this->package().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "package"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 2, this->package(), output); } - + // repeated string dependency = 3; for (int i = 0; i < this->dependency_size(); i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->dependency(i).data(), this->dependency(i).length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "dependency"); ::google::protobuf::internal::WireFormatLite::WriteString( 3, this->dependency(i), output); } - + // repeated .google.protobuf.DescriptorProto message_type = 4; for (int i = 0; i < this->message_type_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 4, this->message_type(i), output); } - + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; for (int i = 0; i < this->enum_type_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 5, this->enum_type(i), output); } - + // repeated .google.protobuf.ServiceDescriptorProto service = 6; for (int i = 0; i < this->service_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 6, this->service(i), output); } - + // repeated .google.protobuf.FieldDescriptorProto extension = 7; for (int i = 0; i < this->extension_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 7, this->extension(i), output); } - + // optional .google.protobuf.FileOptions options = 8; - if (_has_bit(7)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 8, this->options(), output); } - + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (has_source_code_info()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 9, this->source_code_info(), output); + } + + // repeated int32 public_dependency = 10; + for (int i = 0; i < this->public_dependency_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteInt32( + 10, this->public_dependency(i), output); + } + + // repeated int32 weak_dependency = 11; + for (int i = 0; i < this->weak_dependency_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteInt32( + 11, this->weak_dependency(i), output); + } + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.FileDescriptorProto) } ::google::protobuf::uint8* FileDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); } - + // optional string package = 2; - if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_package()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->package().data(), this->package().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "package"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 2, this->package(), target); } - + // repeated string dependency = 3; for (int i = 0; i < this->dependency_size(); i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->dependency(i).data(), this->dependency(i).length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "dependency"); target = ::google::protobuf::internal::WireFormatLite:: WriteStringToArray(3, this->dependency(i), target); } - + // repeated .google.protobuf.DescriptorProto message_type = 4; for (int i = 0; i < this->message_type_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 4, this->message_type(i), target); } - + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; for (int i = 0; i < this->enum_type_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 5, this->enum_type(i), target); } - + // repeated .google.protobuf.ServiceDescriptorProto service = 6; for (int i = 0; i < this->service_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 6, this->service(i), target); } - + // repeated .google.protobuf.FieldDescriptorProto extension = 7; for (int i = 0; i < this->extension_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 7, this->extension(i), target); } - + // optional .google.protobuf.FileOptions options = 8; - if (_has_bit(7)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 8, this->options(), target); } - + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (has_source_code_info()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 9, this->source_code_info(), target); + } + + // repeated int32 public_dependency = 10; + for (int i = 0; i < this->public_dependency_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArray(10, this->public_dependency(i), target); + } + + // repeated int32 weak_dependency = 11; + for (int i = 0; i < this->weak_dependency_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArray(11, this->weak_dependency(i), target); + } + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorProto) return target; } int FileDescriptorProto::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional string name = 1; if (has_name()) { @@ -1245,21 +1497,30 @@ int FileDescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->name()); } - + // optional string package = 2; if (has_package()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->package()); } - + + } + if (_has_bits_[9 / 32] & (0xffu << (9 % 32))) { // optional .google.protobuf.FileOptions options = 8; if (has_options()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } - + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (has_source_code_info()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->source_code_info()); + } + } // repeated string dependency = 3; total_size += 1 * this->dependency_size(); @@ -1267,7 +1528,27 @@ int FileDescriptorProto::ByteSize() const { total_size += ::google::protobuf::internal::WireFormatLite::StringSize( this->dependency(i)); } - + + // repeated int32 public_dependency = 10; + { + int data_size = 0; + for (int i = 0; i < this->public_dependency_size(); i++) { + data_size += ::google::protobuf::internal::WireFormatLite:: + Int32Size(this->public_dependency(i)); + } + total_size += 1 * this->public_dependency_size() + data_size; + } + + // repeated int32 weak_dependency = 11; + { + int data_size = 0; + for (int i = 0; i < this->weak_dependency_size(); i++) { + data_size += ::google::protobuf::internal::WireFormatLite:: + Int32Size(this->weak_dependency(i)); + } + total_size += 1 * this->weak_dependency_size() + data_size; + } + // repeated .google.protobuf.DescriptorProto message_type = 4; total_size += 1 * this->message_type_size(); for (int i = 0; i < this->message_type_size(); i++) { @@ -1275,7 +1556,7 @@ int FileDescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->message_type(i)); } - + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; total_size += 1 * this->enum_type_size(); for (int i = 0; i < this->enum_type_size(); i++) { @@ -1283,7 +1564,7 @@ int FileDescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->enum_type(i)); } - + // repeated .google.protobuf.ServiceDescriptorProto service = 6; total_size += 1 * this->service_size(); for (int i = 0; i < this->service_size(); i++) { @@ -1291,7 +1572,7 @@ int FileDescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->service(i)); } - + // repeated .google.protobuf.FieldDescriptorProto extension = 7; total_size += 1 * this->extension_size(); for (int i = 0; i < this->extension_size(); i++) { @@ -1299,7 +1580,7 @@ int FileDescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->extension(i)); } - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -1326,20 +1607,27 @@ void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) { GOOGLE_CHECK_NE(&from, this); dependency_.MergeFrom(from.dependency_); + public_dependency_.MergeFrom(from.public_dependency_); + weak_dependency_.MergeFrom(from.weak_dependency_); message_type_.MergeFrom(from.message_type_); enum_type_.MergeFrom(from.enum_type_); service_.MergeFrom(from.service_); extension_.MergeFrom(from.extension_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(1)) { + if (from.has_package()) { set_package(from.package()); } - if (from._has_bit(7)) { + } + if (from._has_bits_[9 / 32] & (0xffu << (9 % 32))) { + if (from.has_options()) { mutable_options()->::google::protobuf::FileOptions::MergeFrom(from.options()); } + if (from.has_source_code_info()) { + mutable_source_code_info()->::google::protobuf::SourceCodeInfo::MergeFrom(from.source_code_info()); + } } mutable_unknown_fields()->MergeFrom(from.unknown_fields()); } @@ -1357,19 +1645,11 @@ void FileDescriptorProto::CopyFrom(const FileDescriptorProto& from) { } bool FileDescriptorProto::IsInitialized() const { - - for (int i = 0; i < message_type_size(); i++) { - if (!this->message_type(i).IsInitialized()) return false; - } - for (int i = 0; i < enum_type_size(); i++) { - if (!this->enum_type(i).IsInitialized()) return false; - } - for (int i = 0; i < service_size(); i++) { - if (!this->service(i).IsInitialized()) return false; - } - for (int i = 0; i < extension_size(); i++) { - if (!this->extension(i).IsInitialized()) return false; - } + + if (!::google::protobuf::internal::AllAreInitialized(this->message_type())) return false; + if (!::google::protobuf::internal::AllAreInitialized(this->enum_type())) return false; + if (!::google::protobuf::internal::AllAreInitialized(this->service())) return false; + if (!::google::protobuf::internal::AllAreInitialized(this->extension())) return false; if (has_options()) { if (!this->options().IsInitialized()) return false; } @@ -1381,11 +1661,14 @@ void FileDescriptorProto::Swap(FileDescriptorProto* other) { std::swap(name_, other->name_); std::swap(package_, other->package_); dependency_.Swap(&other->dependency_); + public_dependency_.Swap(&other->public_dependency_); + weak_dependency_.Swap(&other->weak_dependency_); message_type_.Swap(&other->message_type_); enum_type_.Swap(&other->enum_type_); service_.Swap(&other->service_); extension_.Swap(&other->extension_); std::swap(options_, other->options_); + std::swap(source_code_info_, other->source_code_info_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); std::swap(_cached_size_, other->_cached_size_); @@ -1411,6 +1694,7 @@ const int DescriptorProto_ExtensionRange::kEndFieldNumber; DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ExtensionRange) } void DescriptorProto_ExtensionRange::InitAsDefaultInstance() { @@ -1420,6 +1704,7 @@ DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorP : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ExtensionRange) } void DescriptorProto_ExtensionRange::SharedCtor() { @@ -1430,6 +1715,7 @@ void DescriptorProto_ExtensionRange::SharedCtor() { } DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() { + // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ExtensionRange) SharedDtor(); } @@ -1449,7 +1735,8 @@ const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange::descriptor } const DescriptorProto_ExtensionRange& DescriptorProto_ExtensionRange::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::default_instance_ = NULL; @@ -1459,56 +1746,70 @@ DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New() const { } void DescriptorProto_ExtensionRange::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - start_ = 0; - end_ = 0; - } +#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ + &reinterpret_cast(16)->f) - \ + reinterpret_cast(16)) + +#define ZR_(first, last) do { \ + size_t f = OFFSET_OF_FIELD_(first); \ + size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ + ::memset(&first, 0, n); \ + } while (0) + + ZR_(start_, end_); + +#undef OFFSET_OF_FIELD_ +#undef ZR_ + ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); } bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ExtensionRange) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional int32 start = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 8) { DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &start_))); - _set_bit(0); + set_has_start(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(16)) goto parse_end; break; } - + // optional int32 end = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 16) { parse_end: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &end_))); - _set_bit(1); + set_has_end(); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -1516,50 +1817,59 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto.ExtensionRange) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto.ExtensionRange) + return false; #undef DO_ } void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto.ExtensionRange) // optional int32 start = 1; - if (_has_bit(0)) { + if (has_start()) { ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output); } - + // optional int32 end = 2; - if (_has_bit(1)) { + if (has_end()) { ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto.ExtensionRange) } ::google::protobuf::uint8* DescriptorProto_ExtensionRange::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ExtensionRange) // optional int32 start = 1; - if (_has_bit(0)) { + if (has_start()) { target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target); } - + // optional int32 end = 2; - if (_has_bit(1)) { + if (has_end()) { target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ExtensionRange) return target; } int DescriptorProto_ExtensionRange::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional int32 start = 1; if (has_start()) { @@ -1567,14 +1877,14 @@ int DescriptorProto_ExtensionRange::ByteSize() const { ::google::protobuf::internal::WireFormatLite::Int32Size( this->start()); } - + // optional int32 end = 2; if (has_end()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::Int32Size( this->end()); } - + } if (!unknown_fields().empty()) { total_size += @@ -1602,10 +1912,10 @@ void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_start()) { set_start(from.start()); } - if (from._has_bit(1)) { + if (from.has_end()) { set_end(from.end()); } } @@ -1625,7 +1935,7 @@ void DescriptorProto_ExtensionRange::CopyFrom(const DescriptorProto_ExtensionRan } bool DescriptorProto_ExtensionRange::IsInitialized() const { - + return true; } @@ -1650,7 +1960,6 @@ void DescriptorProto_ExtensionRange::Swap(DescriptorProto_ExtensionRange* other) // ------------------------------------------------------------------- -const ::std::string DescriptorProto::_default_name_; #ifndef _MSC_VER const int DescriptorProto::kNameFieldNumber; const int DescriptorProto::kFieldFieldNumber; @@ -1658,12 +1967,14 @@ const int DescriptorProto::kExtensionFieldNumber; const int DescriptorProto::kNestedTypeFieldNumber; const int DescriptorProto::kEnumTypeFieldNumber; const int DescriptorProto::kExtensionRangeFieldNumber; +const int DescriptorProto::kOneofDeclFieldNumber; const int DescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER DescriptorProto::DescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto) } void DescriptorProto::InitAsDefaultInstance() { @@ -1674,21 +1985,24 @@ DescriptorProto::DescriptorProto(const DescriptorProto& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto) } void DescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } DescriptorProto::~DescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto) SharedDtor(); } void DescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (this != default_instance_) { @@ -1707,7 +2021,8 @@ const ::google::protobuf::Descriptor* DescriptorProto::descriptor() { } const DescriptorProto& DescriptorProto::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } DescriptorProto* DescriptorProto::default_instance_ = NULL; @@ -1717,13 +2032,13 @@ DescriptorProto* DescriptorProto::New() const { } void DescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (_has_bits_[0 / 32] & 129) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } - if (_has_bit(6)) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); } } @@ -1732,126 +2047,140 @@ void DescriptorProto::Clear() { nested_type_.Clear(); enum_type_.Clear(); extension_range_.Clear(); + oneof_decl_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); } bool DescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_field; break; } - + // repeated .google.protobuf.FieldDescriptorProto field = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_field: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_field())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_field; if (input->ExpectTag(26)) goto parse_nested_type; break; } - + // repeated .google.protobuf.DescriptorProto nested_type = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_nested_type: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_nested_type())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(26)) goto parse_nested_type; if (input->ExpectTag(34)) goto parse_enum_type; break; } - + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; case 4: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 34) { parse_enum_type: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_enum_type())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(34)) goto parse_enum_type; if (input->ExpectTag(42)) goto parse_extension_range; break; } - + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; case 5: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 42) { parse_extension_range: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_extension_range())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(42)) goto parse_extension_range; if (input->ExpectTag(50)) goto parse_extension; break; } - + // repeated .google.protobuf.FieldDescriptorProto extension = 6; case 6: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 50) { parse_extension: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_extension())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(50)) goto parse_extension; if (input->ExpectTag(58)) goto parse_options; break; } - + // optional .google.protobuf.MessageOptions options = 7; case 7: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 58) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; + } + if (input->ExpectTag(66)) goto parse_oneof_decl; + break; + } + + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + case 8: { + if (tag == 66) { + parse_oneof_decl: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_oneof_decl())); + } else { + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectTag(66)) goto parse_oneof_decl; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -1859,127 +2188,151 @@ bool DescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto) + return false; #undef DO_ } void DescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } - + // repeated .google.protobuf.FieldDescriptorProto field = 2; for (int i = 0; i < this->field_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 2, this->field(i), output); } - + // repeated .google.protobuf.DescriptorProto nested_type = 3; for (int i = 0; i < this->nested_type_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 3, this->nested_type(i), output); } - + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; for (int i = 0; i < this->enum_type_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 4, this->enum_type(i), output); } - + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; for (int i = 0; i < this->extension_range_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 5, this->extension_range(i), output); } - + // repeated .google.protobuf.FieldDescriptorProto extension = 6; for (int i = 0; i < this->extension_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 6, this->extension(i), output); } - + // optional .google.protobuf.MessageOptions options = 7; - if (_has_bit(6)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 7, this->options(), output); } - + + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + for (int i = 0; i < this->oneof_decl_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 8, this->oneof_decl(i), output); + } + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto) } ::google::protobuf::uint8* DescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); } - + // repeated .google.protobuf.FieldDescriptorProto field = 2; for (int i = 0; i < this->field_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 2, this->field(i), target); } - + // repeated .google.protobuf.DescriptorProto nested_type = 3; for (int i = 0; i < this->nested_type_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 3, this->nested_type(i), target); } - + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; for (int i = 0; i < this->enum_type_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 4, this->enum_type(i), target); } - + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; for (int i = 0; i < this->extension_range_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 5, this->extension_range(i), target); } - + // repeated .google.protobuf.FieldDescriptorProto extension = 6; for (int i = 0; i < this->extension_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 6, this->extension(i), target); } - + // optional .google.protobuf.MessageOptions options = 7; - if (_has_bit(6)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 7, this->options(), target); } - + + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + for (int i = 0; i < this->oneof_decl_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 8, this->oneof_decl(i), target); + } + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto) return target; } int DescriptorProto::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional string name = 1; if (has_name()) { @@ -1987,14 +2340,14 @@ int DescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->name()); } - + // optional .google.protobuf.MessageOptions options = 7; if (has_options()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } - + } // repeated .google.protobuf.FieldDescriptorProto field = 2; total_size += 1 * this->field_size(); @@ -2003,7 +2356,7 @@ int DescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->field(i)); } - + // repeated .google.protobuf.FieldDescriptorProto extension = 6; total_size += 1 * this->extension_size(); for (int i = 0; i < this->extension_size(); i++) { @@ -2011,7 +2364,7 @@ int DescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->extension(i)); } - + // repeated .google.protobuf.DescriptorProto nested_type = 3; total_size += 1 * this->nested_type_size(); for (int i = 0; i < this->nested_type_size(); i++) { @@ -2019,7 +2372,7 @@ int DescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->nested_type(i)); } - + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; total_size += 1 * this->enum_type_size(); for (int i = 0; i < this->enum_type_size(); i++) { @@ -2027,7 +2380,7 @@ int DescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->enum_type(i)); } - + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; total_size += 1 * this->extension_range_size(); for (int i = 0; i < this->extension_range_size(); i++) { @@ -2035,7 +2388,15 @@ int DescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->extension_range(i)); } - + + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + total_size += 1 * this->oneof_decl_size(); + for (int i = 0; i < this->oneof_decl_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->oneof_decl(i)); + } + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -2066,11 +2427,12 @@ void DescriptorProto::MergeFrom(const DescriptorProto& from) { nested_type_.MergeFrom(from.nested_type_); enum_type_.MergeFrom(from.enum_type_); extension_range_.MergeFrom(from.extension_range_); + oneof_decl_.MergeFrom(from.oneof_decl_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(6)) { + if (from.has_options()) { mutable_options()->::google::protobuf::MessageOptions::MergeFrom(from.options()); } } @@ -2090,19 +2452,11 @@ void DescriptorProto::CopyFrom(const DescriptorProto& from) { } bool DescriptorProto::IsInitialized() const { - - for (int i = 0; i < field_size(); i++) { - if (!this->field(i).IsInitialized()) return false; - } - for (int i = 0; i < extension_size(); i++) { - if (!this->extension(i).IsInitialized()) return false; - } - for (int i = 0; i < nested_type_size(); i++) { - if (!this->nested_type(i).IsInitialized()) return false; - } - for (int i = 0; i < enum_type_size(); i++) { - if (!this->enum_type(i).IsInitialized()) return false; - } + + if (!::google::protobuf::internal::AllAreInitialized(this->field())) return false; + if (!::google::protobuf::internal::AllAreInitialized(this->extension())) return false; + if (!::google::protobuf::internal::AllAreInitialized(this->nested_type())) return false; + if (!::google::protobuf::internal::AllAreInitialized(this->enum_type())) return false; if (has_options()) { if (!this->options().IsInitialized()) return false; } @@ -2117,6 +2471,7 @@ void DescriptorProto::Swap(DescriptorProto* other) { nested_type_.Swap(&other->nested_type_); enum_type_.Swap(&other->enum_type_); extension_range_.Swap(&other->extension_range_); + oneof_decl_.Swap(&other->oneof_decl_); std::swap(options_, other->options_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -2211,10 +2566,6 @@ const FieldDescriptorProto_Label FieldDescriptorProto::Label_MIN; const FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX; const int FieldDescriptorProto::Label_ARRAYSIZE; #endif // _MSC_VER -const ::std::string FieldDescriptorProto::_default_name_; -const ::std::string FieldDescriptorProto::_default_type_name_; -const ::std::string FieldDescriptorProto::_default_extendee_; -const ::std::string FieldDescriptorProto::_default_default_value_; #ifndef _MSC_VER const int FieldDescriptorProto::kNameFieldNumber; const int FieldDescriptorProto::kNumberFieldNumber; @@ -2223,12 +2574,14 @@ const int FieldDescriptorProto::kTypeFieldNumber; const int FieldDescriptorProto::kTypeNameFieldNumber; const int FieldDescriptorProto::kExtendeeFieldNumber; const int FieldDescriptorProto::kDefaultValueFieldNumber; +const int FieldDescriptorProto::kOneofIndexFieldNumber; const int FieldDescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER FieldDescriptorProto::FieldDescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.FieldDescriptorProto) } void FieldDescriptorProto::InitAsDefaultInstance() { @@ -2239,36 +2592,40 @@ FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldDescriptorProto) } void FieldDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); number_ = 0; label_ = 1; type_ = 1; - type_name_ = const_cast< ::std::string*>(&_default_type_name_); - extendee_ = const_cast< ::std::string*>(&_default_extendee_); - default_value_ = const_cast< ::std::string*>(&_default_default_value_); + type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + oneof_index_ = 0; options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } FieldDescriptorProto::~FieldDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.FieldDescriptorProto) SharedDtor(); } void FieldDescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } - if (type_name_ != &_default_type_name_) { + if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete type_name_; } - if (extendee_ != &_default_extendee_) { + if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete extendee_; } - if (default_value_ != &_default_default_value_) { + if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete default_value_; } if (this != default_instance_) { @@ -2287,7 +2644,8 @@ const ::google::protobuf::Descriptor* FieldDescriptorProto::descriptor() { } const FieldDescriptorProto& FieldDescriptorProto::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } FieldDescriptorProto* FieldDescriptorProto::default_instance_ = NULL; @@ -2297,33 +2655,34 @@ FieldDescriptorProto* FieldDescriptorProto::New() const { } void FieldDescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (_has_bits_[0 / 32] & 255) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } number_ = 0; label_ = 1; type_ = 1; - if (_has_bit(4)) { - if (type_name_ != &_default_type_name_) { + if (has_type_name()) { + if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { type_name_->clear(); } } - if (_has_bit(5)) { - if (extendee_ != &_default_extendee_) { + if (has_extendee()) { + if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { extendee_->clear(); } } - if (_has_bit(6)) { - if (default_value_ != &_default_default_value_) { + if (has_default_value()) { + if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { default_value_->clear(); } } - if (_has_bit(7)) { - if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); - } + oneof_index_ = 0; + } + if (has_options()) { + if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); } ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -2331,63 +2690,65 @@ void FieldDescriptorProto::Clear() { bool FieldDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.FieldDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_extendee; break; } - + // optional string extendee = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_extendee: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_extendee())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->extendee().data(), this->extendee().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "extendee"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(24)) goto parse_number; break; } - + // optional int32 number = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 24) { parse_number: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &number_))); - _set_bit(1); + set_has_number(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(32)) goto parse_label; break; } - + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; case 4: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 32) { parse_label: int value; DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< @@ -2399,16 +2760,15 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( mutable_unknown_fields()->AddVarint(4, value); } } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(40)) goto parse_type; break; } - + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; case 5: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 40) { parse_type: int value; DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< @@ -2420,65 +2780,80 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( mutable_unknown_fields()->AddVarint(5, value); } } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(50)) goto parse_type_name; break; } - + // optional string type_name = 6; case 6: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 50) { parse_type_name: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_type_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->type_name().data(), this->type_name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "type_name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(58)) goto parse_default_value; break; } - + // optional string default_value = 7; case 7: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 58) { parse_default_value: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_default_value())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->default_value().data(), this->default_value().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "default_value"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(66)) goto parse_options; break; } - + // optional .google.protobuf.FieldOptions options = 8; case 8: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 66) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; + } + if (input->ExpectTag(72)) goto parse_oneof_index; + break; + } + + // optional int32 oneof_index = 9; + case 9: { + if (tag == 72) { + parse_oneof_index: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &oneof_index_))); + set_has_oneof_index(); + } else { + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -2486,153 +2861,180 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.FieldDescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.FieldDescriptorProto) + return false; #undef DO_ } void FieldDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.FieldDescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } - + // optional string extendee = 2; - if (_has_bit(5)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_extendee()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->extendee().data(), this->extendee().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "extendee"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 2, this->extendee(), output); } - + // optional int32 number = 3; - if (_has_bit(1)) { + if (has_number()) { ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output); } - + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; - if (_has_bit(2)) { + if (has_label()) { ::google::protobuf::internal::WireFormatLite::WriteEnum( 4, this->label(), output); } - + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - if (_has_bit(3)) { + if (has_type()) { ::google::protobuf::internal::WireFormatLite::WriteEnum( 5, this->type(), output); } - + // optional string type_name = 6; - if (_has_bit(4)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_type_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->type_name().data(), this->type_name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "type_name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 6, this->type_name(), output); } - + // optional string default_value = 7; - if (_has_bit(6)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_default_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->default_value().data(), this->default_value().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "default_value"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 7, this->default_value(), output); } - + // optional .google.protobuf.FieldOptions options = 8; - if (_has_bit(7)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 8, this->options(), output); } - + + // optional int32 oneof_index = 9; + if (has_oneof_index()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(9, this->oneof_index(), output); + } + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.FieldDescriptorProto) } ::google::protobuf::uint8* FieldDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldDescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); } - + // optional string extendee = 2; - if (_has_bit(5)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_extendee()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->extendee().data(), this->extendee().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "extendee"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 2, this->extendee(), target); } - + // optional int32 number = 3; - if (_has_bit(1)) { + if (has_number()) { target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target); } - + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; - if (_has_bit(2)) { + if (has_label()) { target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( 4, this->label(), target); } - + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - if (_has_bit(3)) { + if (has_type()) { target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( 5, this->type(), target); } - + // optional string type_name = 6; - if (_has_bit(4)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_type_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->type_name().data(), this->type_name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "type_name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 6, this->type_name(), target); } - + // optional string default_value = 7; - if (_has_bit(6)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_default_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->default_value().data(), this->default_value().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "default_value"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 7, this->default_value(), target); } - + // optional .google.protobuf.FieldOptions options = 8; - if (_has_bit(7)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 8, this->options(), target); } - + + // optional int32 oneof_index = 9; + if (has_oneof_index()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(9, this->oneof_index(), target); + } + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldDescriptorProto) return target; } int FieldDescriptorProto::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional string name = 1; if (has_name()) { @@ -2640,54 +3042,63 @@ int FieldDescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->name()); } - + // optional int32 number = 3; if (has_number()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::Int32Size( this->number()); } - + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; if (has_label()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::EnumSize(this->label()); } - + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; if (has_type()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::EnumSize(this->type()); } - + // optional string type_name = 6; if (has_type_name()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->type_name()); } - + // optional string extendee = 2; if (has_extendee()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->extendee()); } - + // optional string default_value = 7; if (has_default_value()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->default_value()); } - + + // optional int32 oneof_index = 9; + if (has_oneof_index()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->oneof_index()); + } + + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { // optional .google.protobuf.FieldOptions options = 8; if (has_options()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } - + } if (!unknown_fields().empty()) { total_size += @@ -2715,28 +3126,33 @@ void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(1)) { + if (from.has_number()) { set_number(from.number()); } - if (from._has_bit(2)) { + if (from.has_label()) { set_label(from.label()); } - if (from._has_bit(3)) { + if (from.has_type()) { set_type(from.type()); } - if (from._has_bit(4)) { + if (from.has_type_name()) { set_type_name(from.type_name()); } - if (from._has_bit(5)) { + if (from.has_extendee()) { set_extendee(from.extendee()); } - if (from._has_bit(6)) { + if (from.has_default_value()) { set_default_value(from.default_value()); } - if (from._has_bit(7)) { + if (from.has_oneof_index()) { + set_oneof_index(from.oneof_index()); + } + } + if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) { + if (from.has_options()) { mutable_options()->::google::protobuf::FieldOptions::MergeFrom(from.options()); } } @@ -2756,7 +3172,7 @@ void FieldDescriptorProto::CopyFrom(const FieldDescriptorProto& from) { } bool FieldDescriptorProto::IsInitialized() const { - + if (has_options()) { if (!this->options().IsInitialized()) return false; } @@ -2772,6 +3188,7 @@ void FieldDescriptorProto::Swap(FieldDescriptorProto* other) { std::swap(type_name_, other->type_name_); std::swap(extendee_, other->extendee_); std::swap(default_value_, other->default_value_); + std::swap(oneof_index_, other->oneof_index_); std::swap(options_, other->options_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -2790,7 +3207,249 @@ void FieldDescriptorProto::Swap(FieldDescriptorProto* other) { // =================================================================== -const ::std::string EnumDescriptorProto::_default_name_; +#ifndef _MSC_VER +const int OneofDescriptorProto::kNameFieldNumber; +#endif // !_MSC_VER + +OneofDescriptorProto::OneofDescriptorProto() + : ::google::protobuf::Message() { + SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.OneofDescriptorProto) +} + +void OneofDescriptorProto::InitAsDefaultInstance() { +} + +OneofDescriptorProto::OneofDescriptorProto(const OneofDescriptorProto& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofDescriptorProto) +} + +void OneofDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); + _cached_size_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +OneofDescriptorProto::~OneofDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.OneofDescriptorProto) + SharedDtor(); +} + +void OneofDescriptorProto::SharedDtor() { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_; + } + if (this != default_instance_) { + } +} + +void OneofDescriptorProto::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* OneofDescriptorProto::descriptor() { + protobuf_AssignDescriptorsOnce(); + return OneofDescriptorProto_descriptor_; +} + +const OneofDescriptorProto& OneofDescriptorProto::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +OneofDescriptorProto* OneofDescriptorProto::default_instance_ = NULL; + +OneofDescriptorProto* OneofDescriptorProto::New() const { + return new OneofDescriptorProto; +} + +void OneofDescriptorProto::Clear() { + if (has_name()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + name_->clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool OneofDescriptorProto::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:google.protobuf.OneofDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string name = 1; + case 1: { + if (tag == 10) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE, + "name"); + } else { + goto handle_unusual; + } + if (input->ExpectAtEnd()) goto success; + break; + } + + default: { + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.OneofDescriptorProto) + return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.OneofDescriptorProto) + return false; +#undef DO_ +} + +void OneofDescriptorProto::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.OneofDescriptorProto) + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 1, this->name(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } + // @@protoc_insertion_point(serialize_end:google.protobuf.OneofDescriptorProto) +} + +::google::protobuf::uint8* OneofDescriptorProto::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofDescriptorProto) + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofDescriptorProto) + return target; +} + +int OneofDescriptorProto::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional string name = 1; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const OneofDescriptorProto* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name()) { + set_name(from.name()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void OneofDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void OneofDescriptorProto::CopyFrom(const OneofDescriptorProto& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool OneofDescriptorProto::IsInitialized() const { + + return true; +} + +void OneofDescriptorProto::Swap(OneofDescriptorProto* other) { + if (other != this) { + std::swap(name_, other->name_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata OneofDescriptorProto::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = OneofDescriptorProto_descriptor_; + metadata.reflection = OneofDescriptorProto_reflection_; + return metadata; +} + + +// =================================================================== + #ifndef _MSC_VER const int EnumDescriptorProto::kNameFieldNumber; const int EnumDescriptorProto::kValueFieldNumber; @@ -2800,6 +3459,7 @@ const int EnumDescriptorProto::kOptionsFieldNumber; EnumDescriptorProto::EnumDescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.EnumDescriptorProto) } void EnumDescriptorProto::InitAsDefaultInstance() { @@ -2810,21 +3470,24 @@ EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto) } void EnumDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } EnumDescriptorProto::~EnumDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumDescriptorProto) SharedDtor(); } void EnumDescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (this != default_instance_) { @@ -2843,7 +3506,8 @@ const ::google::protobuf::Descriptor* EnumDescriptorProto::descriptor() { } const EnumDescriptorProto& EnumDescriptorProto::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } EnumDescriptorProto* EnumDescriptorProto::default_instance_ = NULL; @@ -2853,13 +3517,13 @@ EnumDescriptorProto* EnumDescriptorProto::New() const { } void EnumDescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (_has_bits_[0 / 32] & 5) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } - if (_has_bit(2)) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear(); } } @@ -2870,60 +3534,63 @@ void EnumDescriptorProto::Clear() { bool EnumDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.EnumDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_value; break; } - + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_value: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_value())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_value; if (input->ExpectTag(26)) goto parse_options; break; } - + // optional .google.protobuf.EnumOptions options = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -2931,75 +3598,86 @@ bool EnumDescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.EnumDescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.EnumDescriptorProto) + return false; #undef DO_ } void EnumDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.EnumDescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } - + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; for (int i = 0; i < this->value_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 2, this->value(i), output); } - + // optional .google.protobuf.EnumOptions options = 3; - if (_has_bit(2)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 3, this->options(), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.EnumDescriptorProto) } ::google::protobuf::uint8* EnumDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); } - + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; for (int i = 0; i < this->value_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 2, this->value(i), target); } - + // optional .google.protobuf.EnumOptions options = 3; - if (_has_bit(2)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 3, this->options(), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto) return target; } int EnumDescriptorProto::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional string name = 1; if (has_name()) { @@ -3007,14 +3685,14 @@ int EnumDescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->name()); } - + // optional .google.protobuf.EnumOptions options = 3; if (has_options()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } - + } // repeated .google.protobuf.EnumValueDescriptorProto value = 2; total_size += 1 * this->value_size(); @@ -3023,7 +3701,7 @@ int EnumDescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->value(i)); } - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -3051,10 +3729,10 @@ void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) { GOOGLE_CHECK_NE(&from, this); value_.MergeFrom(from.value_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(2)) { + if (from.has_options()) { mutable_options()->::google::protobuf::EnumOptions::MergeFrom(from.options()); } } @@ -3074,10 +3752,8 @@ void EnumDescriptorProto::CopyFrom(const EnumDescriptorProto& from) { } bool EnumDescriptorProto::IsInitialized() const { - - for (int i = 0; i < value_size(); i++) { - if (!this->value(i).IsInitialized()) return false; - } + + if (!::google::protobuf::internal::AllAreInitialized(this->value())) return false; if (has_options()) { if (!this->options().IsInitialized()) return false; } @@ -3106,7 +3782,6 @@ void EnumDescriptorProto::Swap(EnumDescriptorProto* other) { // =================================================================== -const ::std::string EnumValueDescriptorProto::_default_name_; #ifndef _MSC_VER const int EnumValueDescriptorProto::kNameFieldNumber; const int EnumValueDescriptorProto::kNumberFieldNumber; @@ -3116,6 +3791,7 @@ const int EnumValueDescriptorProto::kOptionsFieldNumber; EnumValueDescriptorProto::EnumValueDescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.EnumValueDescriptorProto) } void EnumValueDescriptorProto::InitAsDefaultInstance() { @@ -3126,22 +3802,25 @@ EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProt : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueDescriptorProto) } void EnumValueDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); number_ = 0; options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } EnumValueDescriptorProto::~EnumValueDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumValueDescriptorProto) SharedDtor(); } void EnumValueDescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (this != default_instance_) { @@ -3160,7 +3839,8 @@ const ::google::protobuf::Descriptor* EnumValueDescriptorProto::descriptor() { } const EnumValueDescriptorProto& EnumValueDescriptorProto::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } EnumValueDescriptorProto* EnumValueDescriptorProto::default_instance_ = NULL; @@ -3170,14 +3850,14 @@ EnumValueDescriptorProto* EnumValueDescriptorProto::New() const { } void EnumValueDescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (_has_bits_[0 / 32] & 7) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } number_ = 0; - if (_has_bit(2)) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear(); } } @@ -3187,61 +3867,64 @@ void EnumValueDescriptorProto::Clear() { bool EnumValueDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.EnumValueDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(16)) goto parse_number; break; } - + // optional int32 number = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 16) { parse_number: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &number_))); - _set_bit(1); + set_has_number(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(26)) goto parse_options; break; } - + // optional .google.protobuf.EnumValueOptions options = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -3249,72 +3932,83 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.EnumValueDescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.EnumValueDescriptorProto) + return false; #undef DO_ } void EnumValueDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.EnumValueDescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } - + // optional int32 number = 2; - if (_has_bit(1)) { + if (has_number()) { ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output); } - + // optional .google.protobuf.EnumValueOptions options = 3; - if (_has_bit(2)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 3, this->options(), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValueDescriptorProto) } ::google::protobuf::uint8* EnumValueDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueDescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); } - + // optional int32 number = 2; - if (_has_bit(1)) { + if (has_number()) { target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target); } - + // optional .google.protobuf.EnumValueOptions options = 3; - if (_has_bit(2)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 3, this->options(), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueDescriptorProto) return target; } int EnumValueDescriptorProto::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional string name = 1; if (has_name()) { @@ -3322,21 +4016,21 @@ int EnumValueDescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->name()); } - + // optional int32 number = 2; if (has_number()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::Int32Size( this->number()); } - + // optional .google.protobuf.EnumValueOptions options = 3; if (has_options()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } - + } if (!unknown_fields().empty()) { total_size += @@ -3364,13 +4058,13 @@ void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(1)) { + if (from.has_number()) { set_number(from.number()); } - if (from._has_bit(2)) { + if (from.has_options()) { mutable_options()->::google::protobuf::EnumValueOptions::MergeFrom(from.options()); } } @@ -3390,7 +4084,7 @@ void EnumValueDescriptorProto::CopyFrom(const EnumValueDescriptorProto& from) { } bool EnumValueDescriptorProto::IsInitialized() const { - + if (has_options()) { if (!this->options().IsInitialized()) return false; } @@ -3419,7 +4113,6 @@ void EnumValueDescriptorProto::Swap(EnumValueDescriptorProto* other) { // =================================================================== -const ::std::string ServiceDescriptorProto::_default_name_; #ifndef _MSC_VER const int ServiceDescriptorProto::kNameFieldNumber; const int ServiceDescriptorProto::kMethodFieldNumber; @@ -3429,6 +4122,7 @@ const int ServiceDescriptorProto::kOptionsFieldNumber; ServiceDescriptorProto::ServiceDescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.ServiceDescriptorProto) } void ServiceDescriptorProto::InitAsDefaultInstance() { @@ -3439,21 +4133,24 @@ ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& fro : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceDescriptorProto) } void ServiceDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } ServiceDescriptorProto::~ServiceDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.ServiceDescriptorProto) SharedDtor(); } void ServiceDescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (this != default_instance_) { @@ -3472,7 +4169,8 @@ const ::google::protobuf::Descriptor* ServiceDescriptorProto::descriptor() { } const ServiceDescriptorProto& ServiceDescriptorProto::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } ServiceDescriptorProto* ServiceDescriptorProto::default_instance_ = NULL; @@ -3482,13 +4180,13 @@ ServiceDescriptorProto* ServiceDescriptorProto::New() const { } void ServiceDescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (_has_bits_[0 / 32] & 5) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } - if (_has_bit(2)) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear(); } } @@ -3499,60 +4197,63 @@ void ServiceDescriptorProto::Clear() { bool ServiceDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.ServiceDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_method; break; } - + // repeated .google.protobuf.MethodDescriptorProto method = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_method: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_method())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_method; if (input->ExpectTag(26)) goto parse_options; break; } - + // optional .google.protobuf.ServiceOptions options = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -3560,75 +4261,86 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.ServiceDescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.ServiceDescriptorProto) + return false; #undef DO_ } void ServiceDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.ServiceDescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } - + // repeated .google.protobuf.MethodDescriptorProto method = 2; for (int i = 0; i < this->method_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 2, this->method(i), output); } - + // optional .google.protobuf.ServiceOptions options = 3; - if (_has_bit(2)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 3, this->options(), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.ServiceDescriptorProto) } ::google::protobuf::uint8* ServiceDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceDescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); } - + // repeated .google.protobuf.MethodDescriptorProto method = 2; for (int i = 0; i < this->method_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 2, this->method(i), target); } - + // optional .google.protobuf.ServiceOptions options = 3; - if (_has_bit(2)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 3, this->options(), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceDescriptorProto) return target; } int ServiceDescriptorProto::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional string name = 1; if (has_name()) { @@ -3636,14 +4348,14 @@ int ServiceDescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->name()); } - + // optional .google.protobuf.ServiceOptions options = 3; if (has_options()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } - + } // repeated .google.protobuf.MethodDescriptorProto method = 2; total_size += 1 * this->method_size(); @@ -3652,7 +4364,7 @@ int ServiceDescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->method(i)); } - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -3680,10 +4392,10 @@ void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) { GOOGLE_CHECK_NE(&from, this); method_.MergeFrom(from.method_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(2)) { + if (from.has_options()) { mutable_options()->::google::protobuf::ServiceOptions::MergeFrom(from.options()); } } @@ -3703,10 +4415,8 @@ void ServiceDescriptorProto::CopyFrom(const ServiceDescriptorProto& from) { } bool ServiceDescriptorProto::IsInitialized() const { - - for (int i = 0; i < method_size(); i++) { - if (!this->method(i).IsInitialized()) return false; - } + + if (!::google::protobuf::internal::AllAreInitialized(this->method())) return false; if (has_options()) { if (!this->options().IsInitialized()) return false; } @@ -3735,9 +4445,6 @@ void ServiceDescriptorProto::Swap(ServiceDescriptorProto* other) { // =================================================================== -const ::std::string MethodDescriptorProto::_default_name_; -const ::std::string MethodDescriptorProto::_default_input_type_; -const ::std::string MethodDescriptorProto::_default_output_type_; #ifndef _MSC_VER const int MethodDescriptorProto::kNameFieldNumber; const int MethodDescriptorProto::kInputTypeFieldNumber; @@ -3748,6 +4455,7 @@ const int MethodDescriptorProto::kOptionsFieldNumber; MethodDescriptorProto::MethodDescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.MethodDescriptorProto) } void MethodDescriptorProto::InitAsDefaultInstance() { @@ -3758,29 +4466,32 @@ MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodDescriptorProto) } void MethodDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); - input_type_ = const_cast< ::std::string*>(&_default_input_type_); - output_type_ = const_cast< ::std::string*>(&_default_output_type_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } MethodDescriptorProto::~MethodDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.MethodDescriptorProto) SharedDtor(); } void MethodDescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } - if (input_type_ != &_default_input_type_) { + if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete input_type_; } - if (output_type_ != &_default_output_type_) { + if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete output_type_; } if (this != default_instance_) { @@ -3799,7 +4510,8 @@ const ::google::protobuf::Descriptor* MethodDescriptorProto::descriptor() { } const MethodDescriptorProto& MethodDescriptorProto::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } MethodDescriptorProto* MethodDescriptorProto::default_instance_ = NULL; @@ -3809,23 +4521,23 @@ MethodDescriptorProto* MethodDescriptorProto::New() const { } void MethodDescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (_has_bits_[0 / 32] & 15) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } - if (_has_bit(1)) { - if (input_type_ != &_default_input_type_) { + if (has_input_type()) { + if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { input_type_->clear(); } } - if (_has_bit(2)) { - if (output_type_ != &_default_output_type_) { + if (has_output_type()) { + if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { output_type_->clear(); } } - if (_has_bit(3)) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear(); } } @@ -3835,79 +4547,83 @@ void MethodDescriptorProto::Clear() { bool MethodDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.MethodDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_input_type; break; } - + // optional string input_type = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_input_type: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_input_type())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->input_type().data(), this->input_type().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "input_type"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(26)) goto parse_output_type; break; } - + // optional string output_type = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_output_type: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_output_type())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->output_type().data(), this->output_type().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "output_type"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(34)) goto parse_options; break; } - + // optional .google.protobuf.MethodOptions options = 4; case 4: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 34) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -3915,100 +4631,115 @@ bool MethodDescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.MethodDescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.MethodDescriptorProto) + return false; #undef DO_ } void MethodDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.MethodDescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } - + // optional string input_type = 2; - if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_input_type()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->input_type().data(), this->input_type().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "input_type"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 2, this->input_type(), output); } - + // optional string output_type = 3; - if (_has_bit(2)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_output_type()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->output_type().data(), this->output_type().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "output_type"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 3, this->output_type(), output); } - + // optional .google.protobuf.MethodOptions options = 4; - if (_has_bit(3)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 4, this->options(), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.MethodDescriptorProto) } ::google::protobuf::uint8* MethodDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodDescriptorProto) // optional string name = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); } - + // optional string input_type = 2; - if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_input_type()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->input_type().data(), this->input_type().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "input_type"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 2, this->input_type(), target); } - + // optional string output_type = 3; - if (_has_bit(2)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_output_type()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->output_type().data(), this->output_type().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "output_type"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 3, this->output_type(), target); } - + // optional .google.protobuf.MethodOptions options = 4; - if (_has_bit(3)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 4, this->options(), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodDescriptorProto) return target; } int MethodDescriptorProto::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional string name = 1; if (has_name()) { @@ -4016,28 +4747,28 @@ int MethodDescriptorProto::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->name()); } - + // optional string input_type = 2; if (has_input_type()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->input_type()); } - + // optional string output_type = 3; if (has_output_type()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->output_type()); } - + // optional .google.protobuf.MethodOptions options = 4; if (has_options()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } - + } if (!unknown_fields().empty()) { total_size += @@ -4065,16 +4796,16 @@ void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(1)) { + if (from.has_input_type()) { set_input_type(from.input_type()); } - if (from._has_bit(2)) { + if (from.has_output_type()) { set_output_type(from.output_type()); } - if (from._has_bit(3)) { + if (from.has_options()) { mutable_options()->::google::protobuf::MethodOptions::MergeFrom(from.options()); } } @@ -4094,7 +4825,7 @@ void MethodDescriptorProto::CopyFrom(const MethodDescriptorProto& from) { } bool MethodDescriptorProto::IsInitialized() const { - + if (has_options()) { if (!this->options().IsInitialized()) return false; } @@ -4147,22 +4878,25 @@ const FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN; const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX; const int FileOptions::OptimizeMode_ARRAYSIZE; #endif // _MSC_VER -const ::std::string FileOptions::_default_java_package_; -const ::std::string FileOptions::_default_java_outer_classname_; #ifndef _MSC_VER const int FileOptions::kJavaPackageFieldNumber; const int FileOptions::kJavaOuterClassnameFieldNumber; const int FileOptions::kJavaMultipleFilesFieldNumber; +const int FileOptions::kJavaGenerateEqualsAndHashFieldNumber; +const int FileOptions::kJavaStringCheckUtf8FieldNumber; const int FileOptions::kOptimizeForFieldNumber; +const int FileOptions::kGoPackageFieldNumber; const int FileOptions::kCcGenericServicesFieldNumber; const int FileOptions::kJavaGenericServicesFieldNumber; const int FileOptions::kPyGenericServicesFieldNumber; +const int FileOptions::kDeprecatedFieldNumber; const int FileOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER FileOptions::FileOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.FileOptions) } void FileOptions::InitAsDefaultInstance() { @@ -4172,31 +4906,41 @@ FileOptions::FileOptions(const FileOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FileOptions) } void FileOptions::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - java_package_ = const_cast< ::std::string*>(&_default_java_package_); - java_outer_classname_ = const_cast< ::std::string*>(&_default_java_outer_classname_); + java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); java_multiple_files_ = false; + java_generate_equals_and_hash_ = false; + java_string_check_utf8_ = false; optimize_for_ = 1; - cc_generic_services_ = true; - java_generic_services_ = true; - py_generic_services_ = true; + go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + cc_generic_services_ = false; + java_generic_services_ = false; + py_generic_services_ = false; + deprecated_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } FileOptions::~FileOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.FileOptions) SharedDtor(); } void FileOptions::SharedDtor() { - if (java_package_ != &_default_java_package_) { + if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete java_package_; } - if (java_outer_classname_ != &_default_java_outer_classname_) { + if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete java_outer_classname_; } + if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete go_package_; + } if (this != default_instance_) { } } @@ -4212,7 +4956,8 @@ const ::google::protobuf::Descriptor* FileOptions::descriptor() { } const FileOptions& FileOptions::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } FileOptions* FileOptions::default_instance_ = NULL; @@ -4223,23 +4968,40 @@ FileOptions* FileOptions::New() const { void FileOptions::Clear() { _extensions_.Clear(); - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (java_package_ != &_default_java_package_) { +#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ + &reinterpret_cast(16)->f) - \ + reinterpret_cast(16)) + +#define ZR_(first, last) do { \ + size_t f = OFFSET_OF_FIELD_(first); \ + size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ + ::memset(&first, 0, n); \ + } while (0) + + if (_has_bits_[0 / 32] & 255) { + ZR_(java_multiple_files_, cc_generic_services_); + if (has_java_package()) { + if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_package_->clear(); } } - if (_has_bit(1)) { - if (java_outer_classname_ != &_default_java_outer_classname_) { + if (has_java_outer_classname()) { + if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_outer_classname_->clear(); } } - java_multiple_files_ = false; optimize_for_ = 1; - cc_generic_services_ = true; - java_generic_services_ = true; - py_generic_services_ = true; + if (has_go_package()) { + if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + go_package_->clear(); + } + } } + ZR_(java_generic_services_, deprecated_); + +#undef OFFSET_OF_FIELD_ +#undef ZR_ + uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -4247,47 +5009,50 @@ void FileOptions::Clear() { bool FileOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.FileOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string java_package = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_java_package())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->java_package().data(), this->java_package().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "java_package"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(66)) goto parse_java_outer_classname; break; } - + // optional string java_outer_classname = 8; case 8: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 66) { parse_java_outer_classname: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_java_outer_classname())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->java_outer_classname().data(), this->java_outer_classname().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "java_outer_classname"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(72)) goto parse_optimize_for; break; } - + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; case 9: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 72) { parse_optimize_for: int value; DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< @@ -4299,96 +5064,154 @@ bool FileOptions::MergePartialFromCodedStream( mutable_unknown_fields()->AddVarint(9, value); } } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(80)) goto parse_java_multiple_files; break; } - + // optional bool java_multiple_files = 10 [default = false]; case 10: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 80) { parse_java_multiple_files: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &java_multiple_files_))); - _set_bit(2); + set_has_java_multiple_files(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(90)) goto parse_go_package; + break; + } + + // optional string go_package = 11; + case 11: { + if (tag == 90) { + parse_go_package: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_go_package())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->go_package().data(), this->go_package().length(), + ::google::protobuf::internal::WireFormat::PARSE, + "go_package"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(128)) goto parse_cc_generic_services; break; } - - // optional bool cc_generic_services = 16 [default = true]; + + // optional bool cc_generic_services = 16 [default = false]; case 16: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 128) { parse_cc_generic_services: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &cc_generic_services_))); - _set_bit(4); + set_has_cc_generic_services(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(136)) goto parse_java_generic_services; break; } - - // optional bool java_generic_services = 17 [default = true]; + + // optional bool java_generic_services = 17 [default = false]; case 17: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 136) { parse_java_generic_services: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &java_generic_services_))); - _set_bit(5); + set_has_java_generic_services(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(144)) goto parse_py_generic_services; break; } - - // optional bool py_generic_services = 18 [default = true]; + + // optional bool py_generic_services = 18 [default = false]; case 18: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 144) { parse_py_generic_services: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &py_generic_services_))); - _set_bit(6); + set_has_py_generic_services(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(160)) goto parse_java_generate_equals_and_hash; + break; + } + + // optional bool java_generate_equals_and_hash = 20 [default = false]; + case 20: { + if (tag == 160) { + parse_java_generate_equals_and_hash: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &java_generate_equals_and_hash_))); + set_has_java_generate_equals_and_hash(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(184)) goto parse_deprecated; + break; + } + + // optional bool deprecated = 23 [default = false]; + case 23: { + if (tag == 184) { + parse_deprecated: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(216)) goto parse_java_string_check_utf8; + break; + } + + // optional bool java_string_check_utf8 = 27 [default = false]; + case 27: { + if (tag == 216) { + parse_java_string_check_utf8: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &java_string_check_utf8_))); + set_has_java_string_check_utf8(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; } - + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -4401,141 +5224,205 @@ bool FileOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.FileOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.FileOptions) + return false; #undef DO_ } void FileOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.FileOptions) // optional string java_package = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_java_package()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->java_package().data(), this->java_package().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "java_package"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->java_package(), output); } - + // optional string java_outer_classname = 8; - if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_java_outer_classname()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->java_outer_classname().data(), this->java_outer_classname().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "java_outer_classname"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 8, this->java_outer_classname(), output); } - + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - if (_has_bit(3)) { + if (has_optimize_for()) { ::google::protobuf::internal::WireFormatLite::WriteEnum( 9, this->optimize_for(), output); } - + // optional bool java_multiple_files = 10 [default = false]; - if (_has_bit(2)) { + if (has_java_multiple_files()) { ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output); } - - // optional bool cc_generic_services = 16 [default = true]; - if (_has_bit(4)) { + + // optional string go_package = 11; + if (has_go_package()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->go_package().data(), this->go_package().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "go_package"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 11, this->go_package(), output); + } + + // optional bool cc_generic_services = 16 [default = false]; + if (has_cc_generic_services()) { ::google::protobuf::internal::WireFormatLite::WriteBool(16, this->cc_generic_services(), output); } - - // optional bool java_generic_services = 17 [default = true]; - if (_has_bit(5)) { + + // optional bool java_generic_services = 17 [default = false]; + if (has_java_generic_services()) { ::google::protobuf::internal::WireFormatLite::WriteBool(17, this->java_generic_services(), output); } - - // optional bool py_generic_services = 18 [default = true]; - if (_has_bit(6)) { + + // optional bool py_generic_services = 18 [default = false]; + if (has_py_generic_services()) { ::google::protobuf::internal::WireFormatLite::WriteBool(18, this->py_generic_services(), output); } - + + // optional bool java_generate_equals_and_hash = 20 [default = false]; + if (has_java_generate_equals_and_hash()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(20, this->java_generate_equals_and_hash(), output); + } + + // optional bool deprecated = 23 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(23, this->deprecated(), output); + } + + // optional bool java_string_check_utf8 = 27 [default = false]; + if (has_java_string_check_utf8()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(27, this->java_string_check_utf8(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 999, this->uninterpreted_option(i), output); } - + // Extension range [1000, 536870912) _extensions_.SerializeWithCachedSizes( 1000, 536870912, output); - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.FileOptions) } ::google::protobuf::uint8* FileOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileOptions) // optional string java_package = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_java_package()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->java_package().data(), this->java_package().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "java_package"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->java_package(), target); } - + // optional string java_outer_classname = 8; - if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_java_outer_classname()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->java_outer_classname().data(), this->java_outer_classname().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "java_outer_classname"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 8, this->java_outer_classname(), target); } - + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - if (_has_bit(3)) { + if (has_optimize_for()) { target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( 9, this->optimize_for(), target); } - + // optional bool java_multiple_files = 10 [default = false]; - if (_has_bit(2)) { + if (has_java_multiple_files()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target); } - - // optional bool cc_generic_services = 16 [default = true]; - if (_has_bit(4)) { + + // optional string go_package = 11; + if (has_go_package()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->go_package().data(), this->go_package().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "go_package"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 11, this->go_package(), target); + } + + // optional bool cc_generic_services = 16 [default = false]; + if (has_cc_generic_services()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(16, this->cc_generic_services(), target); } - - // optional bool java_generic_services = 17 [default = true]; - if (_has_bit(5)) { + + // optional bool java_generic_services = 17 [default = false]; + if (has_java_generic_services()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(17, this->java_generic_services(), target); } - - // optional bool py_generic_services = 18 [default = true]; - if (_has_bit(6)) { + + // optional bool py_generic_services = 18 [default = false]; + if (has_py_generic_services()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(18, this->py_generic_services(), target); } - + + // optional bool java_generate_equals_and_hash = 20 [default = false]; + if (has_java_generate_equals_and_hash()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(20, this->java_generate_equals_and_hash(), target); + } + + // optional bool deprecated = 23 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(23, this->deprecated(), target); + } + + // optional bool java_string_check_utf8 = 27 [default = false]; + if (has_java_string_check_utf8()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(27, this->java_string_check_utf8(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 999, this->uninterpreted_option(i), target); } - + // Extension range [1000, 536870912) target = _extensions_.SerializeWithCachedSizesToArray( 1000, 536870912, target); - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileOptions) return target; } int FileOptions::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional string java_package = 1; if (has_java_package()) { @@ -4543,40 +5430,64 @@ int FileOptions::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->java_package()); } - + // optional string java_outer_classname = 8; if (has_java_outer_classname()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->java_outer_classname()); } - + // optional bool java_multiple_files = 10 [default = false]; if (has_java_multiple_files()) { total_size += 1 + 1; } - + + // optional bool java_generate_equals_and_hash = 20 [default = false]; + if (has_java_generate_equals_and_hash()) { + total_size += 2 + 1; + } + + // optional bool java_string_check_utf8 = 27 [default = false]; + if (has_java_string_check_utf8()) { + total_size += 2 + 1; + } + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; if (has_optimize_for()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for()); } - - // optional bool cc_generic_services = 16 [default = true]; + + // optional string go_package = 11; + if (has_go_package()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->go_package()); + } + + // optional bool cc_generic_services = 16 [default = false]; if (has_cc_generic_services()) { total_size += 2 + 1; } - - // optional bool java_generic_services = 17 [default = true]; + + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + // optional bool java_generic_services = 17 [default = false]; if (has_java_generic_services()) { total_size += 2 + 1; } - - // optional bool py_generic_services = 18 [default = true]; + + // optional bool py_generic_services = 18 [default = false]; if (has_py_generic_services()) { total_size += 2 + 1; } - + + // optional bool deprecated = 23 [default = false]; + if (has_deprecated()) { + total_size += 2 + 1; + } + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); @@ -4585,9 +5496,9 @@ int FileOptions::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } - + total_size += _extensions_.ByteSize(); - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -4615,27 +5526,41 @@ void FileOptions::MergeFrom(const FileOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_java_package()) { set_java_package(from.java_package()); } - if (from._has_bit(1)) { + if (from.has_java_outer_classname()) { set_java_outer_classname(from.java_outer_classname()); } - if (from._has_bit(2)) { + if (from.has_java_multiple_files()) { set_java_multiple_files(from.java_multiple_files()); } - if (from._has_bit(3)) { + if (from.has_java_generate_equals_and_hash()) { + set_java_generate_equals_and_hash(from.java_generate_equals_and_hash()); + } + if (from.has_java_string_check_utf8()) { + set_java_string_check_utf8(from.java_string_check_utf8()); + } + if (from.has_optimize_for()) { set_optimize_for(from.optimize_for()); } - if (from._has_bit(4)) { + if (from.has_go_package()) { + set_go_package(from.go_package()); + } + if (from.has_cc_generic_services()) { set_cc_generic_services(from.cc_generic_services()); } - if (from._has_bit(5)) { + } + if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) { + if (from.has_java_generic_services()) { set_java_generic_services(from.java_generic_services()); } - if (from._has_bit(6)) { + if (from.has_py_generic_services()) { set_py_generic_services(from.py_generic_services()); } + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); @@ -4654,11 +5579,9 @@ void FileOptions::CopyFrom(const FileOptions& from) { } bool FileOptions::IsInitialized() const { - - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } - + + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!_extensions_.IsInitialized()) return false; return true; } @@ -4667,10 +5590,14 @@ void FileOptions::Swap(FileOptions* other) { std::swap(java_package_, other->java_package_); std::swap(java_outer_classname_, other->java_outer_classname_); std::swap(java_multiple_files_, other->java_multiple_files_); + std::swap(java_generate_equals_and_hash_, other->java_generate_equals_and_hash_); + std::swap(java_string_check_utf8_, other->java_string_check_utf8_); std::swap(optimize_for_, other->optimize_for_); + std::swap(go_package_, other->go_package_); std::swap(cc_generic_services_, other->cc_generic_services_); std::swap(java_generic_services_, other->java_generic_services_); std::swap(py_generic_services_, other->py_generic_services_); + std::swap(deprecated_, other->deprecated_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -4693,12 +5620,14 @@ void FileOptions::Swap(FileOptions* other) { #ifndef _MSC_VER const int MessageOptions::kMessageSetWireFormatFieldNumber; const int MessageOptions::kNoStandardDescriptorAccessorFieldNumber; +const int MessageOptions::kDeprecatedFieldNumber; const int MessageOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER MessageOptions::MessageOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.MessageOptions) } void MessageOptions::InitAsDefaultInstance() { @@ -4708,16 +5637,19 @@ MessageOptions::MessageOptions(const MessageOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.MessageOptions) } void MessageOptions::SharedCtor() { _cached_size_ = 0; message_set_wire_format_ = false; no_standard_descriptor_accessor_ = false; + deprecated_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } MessageOptions::~MessageOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.MessageOptions) SharedDtor(); } @@ -4737,7 +5669,8 @@ const ::google::protobuf::Descriptor* MessageOptions::descriptor() { } const MessageOptions& MessageOptions::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } MessageOptions* MessageOptions::default_instance_ = NULL; @@ -4748,10 +5681,21 @@ MessageOptions* MessageOptions::New() const { void MessageOptions::Clear() { _extensions_.Clear(); - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - message_set_wire_format_ = false; - no_standard_descriptor_accessor_ = false; - } +#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ + &reinterpret_cast(16)->f) - \ + reinterpret_cast(16)) + +#define ZR_(first, last) do { \ + size_t f = OFFSET_OF_FIELD_(first); \ + size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ + ::memset(&first, 0, n); \ + } while (0) + + ZR_(message_set_wire_format_, deprecated_); + +#undef OFFSET_OF_FIELD_ +#undef ZR_ + uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -4759,61 +5703,78 @@ void MessageOptions::Clear() { bool MessageOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.MessageOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional bool message_set_wire_format = 1 [default = false]; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 8) { DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &message_set_wire_format_))); - _set_bit(0); + set_has_message_set_wire_format(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(16)) goto parse_no_standard_descriptor_accessor; break; } - + // optional bool no_standard_descriptor_accessor = 2 [default = false]; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 16) { parse_no_standard_descriptor_accessor: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &no_standard_descriptor_accessor_))); - _set_bit(1); + set_has_no_standard_descriptor_accessor(); } else { - goto handle_uninterpreted; + goto handle_unusual; + } + if (input->ExpectTag(24)) goto parse_deprecated; + break; + } + + // optional bool deprecated = 3 [default = false]; + case 3: { + if (tag == 24) { + parse_deprecated: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; } - + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -4826,82 +5787,106 @@ bool MessageOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.MessageOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.MessageOptions) + return false; #undef DO_ } void MessageOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.MessageOptions) // optional bool message_set_wire_format = 1 [default = false]; - if (_has_bit(0)) { + if (has_message_set_wire_format()) { ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output); } - + // optional bool no_standard_descriptor_accessor = 2 [default = false]; - if (_has_bit(1)) { + if (has_no_standard_descriptor_accessor()) { ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->no_standard_descriptor_accessor(), output); } - + + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 999, this->uninterpreted_option(i), output); } - + // Extension range [1000, 536870912) _extensions_.SerializeWithCachedSizes( 1000, 536870912, output); - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.MessageOptions) } ::google::protobuf::uint8* MessageOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MessageOptions) // optional bool message_set_wire_format = 1 [default = false]; - if (_has_bit(0)) { + if (has_message_set_wire_format()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target); } - + // optional bool no_standard_descriptor_accessor = 2 [default = false]; - if (_has_bit(1)) { + if (has_no_standard_descriptor_accessor()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->no_standard_descriptor_accessor(), target); } - + + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 999, this->uninterpreted_option(i), target); } - + // Extension range [1000, 536870912) target = _extensions_.SerializeWithCachedSizesToArray( 1000, 536870912, target); - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MessageOptions) return target; } int MessageOptions::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional bool message_set_wire_format = 1 [default = false]; if (has_message_set_wire_format()) { total_size += 1 + 1; } - + // optional bool no_standard_descriptor_accessor = 2 [default = false]; if (has_no_standard_descriptor_accessor()) { total_size += 1 + 1; } - + + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + total_size += 1 + 1; + } + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); @@ -4910,9 +5895,9 @@ int MessageOptions::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } - + total_size += _extensions_.ByteSize(); - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -4940,12 +5925,15 @@ void MessageOptions::MergeFrom(const MessageOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_message_set_wire_format()) { set_message_set_wire_format(from.message_set_wire_format()); } - if (from._has_bit(1)) { + if (from.has_no_standard_descriptor_accessor()) { set_no_standard_descriptor_accessor(from.no_standard_descriptor_accessor()); } + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); @@ -4964,11 +5952,9 @@ void MessageOptions::CopyFrom(const MessageOptions& from) { } bool MessageOptions::IsInitialized() const { - - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } - + + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!_extensions_.IsInitialized()) return false; return true; } @@ -4976,6 +5962,7 @@ void MessageOptions::Swap(MessageOptions* other) { if (other != this) { std::swap(message_set_wire_format_, other->message_set_wire_format_); std::swap(no_standard_descriptor_accessor_, other->no_standard_descriptor_accessor_); + std::swap(deprecated_, other->deprecated_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -5018,18 +6005,20 @@ const FieldOptions_CType FieldOptions::CType_MIN; const FieldOptions_CType FieldOptions::CType_MAX; const int FieldOptions::CType_ARRAYSIZE; #endif // _MSC_VER -const ::std::string FieldOptions::_default_experimental_map_key_; #ifndef _MSC_VER const int FieldOptions::kCtypeFieldNumber; const int FieldOptions::kPackedFieldNumber; +const int FieldOptions::kLazyFieldNumber; const int FieldOptions::kDeprecatedFieldNumber; const int FieldOptions::kExperimentalMapKeyFieldNumber; +const int FieldOptions::kWeakFieldNumber; const int FieldOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER FieldOptions::FieldOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.FieldOptions) } void FieldOptions::InitAsDefaultInstance() { @@ -5039,23 +6028,28 @@ FieldOptions::FieldOptions(const FieldOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldOptions) } void FieldOptions::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; ctype_ = 0; packed_ = false; + lazy_ = false; deprecated_ = false; - experimental_map_key_ = const_cast< ::std::string*>(&_default_experimental_map_key_); + experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + weak_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } FieldOptions::~FieldOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.FieldOptions) SharedDtor(); } void FieldOptions::SharedDtor() { - if (experimental_map_key_ != &_default_experimental_map_key_) { + if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete experimental_map_key_; } if (this != default_instance_) { @@ -5073,7 +6067,8 @@ const ::google::protobuf::Descriptor* FieldOptions::descriptor() { } const FieldOptions& FieldOptions::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } FieldOptions* FieldOptions::default_instance_ = NULL; @@ -5084,16 +6079,28 @@ FieldOptions* FieldOptions::New() const { void FieldOptions::Clear() { _extensions_.Clear(); - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - ctype_ = 0; - packed_ = false; - deprecated_ = false; - if (_has_bit(3)) { - if (experimental_map_key_ != &_default_experimental_map_key_) { +#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ + &reinterpret_cast(16)->f) - \ + reinterpret_cast(16)) + +#define ZR_(first, last) do { \ + size_t f = OFFSET_OF_FIELD_(first); \ + size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ + ::memset(&first, 0, n); \ + } while (0) + + if (_has_bits_[0 / 32] & 63) { + ZR_(ctype_, weak_); + if (has_experimental_map_key()) { + if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { experimental_map_key_->clear(); } } } + +#undef OFFSET_OF_FIELD_ +#undef ZR_ + uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -5101,14 +6108,17 @@ void FieldOptions::Clear() { bool FieldOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.FieldOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 8) { int value; DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( @@ -5119,81 +6129,109 @@ bool FieldOptions::MergePartialFromCodedStream( mutable_unknown_fields()->AddVarint(1, value); } } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(16)) goto parse_packed; break; } - + // optional bool packed = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 16) { parse_packed: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &packed_))); - _set_bit(1); + set_has_packed(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(24)) goto parse_deprecated; break; } - + // optional bool deprecated = 3 [default = false]; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 24) { parse_deprecated: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &deprecated_))); - _set_bit(2); + set_has_deprecated(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(40)) goto parse_lazy; + break; + } + + // optional bool lazy = 5 [default = false]; + case 5: { + if (tag == 40) { + parse_lazy: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &lazy_))); + set_has_lazy(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(74)) goto parse_experimental_map_key; break; } - + // optional string experimental_map_key = 9; case 9: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 74) { parse_experimental_map_key: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_experimental_map_key())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->experimental_map_key().data(), this->experimental_map_key().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "experimental_map_key"); + } else { + goto handle_unusual; + } + if (input->ExpectTag(80)) goto parse_weak; + break; + } + + // optional bool weak = 10 [default = false]; + case 10: { + if (tag == 80) { + parse_weak: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &weak_))); + set_has_weak(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; } - + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -5206,126 +6244,167 @@ bool FieldOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.FieldOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.FieldOptions) + return false; #undef DO_ } void FieldOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.FieldOptions) // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; - if (_has_bit(0)) { + if (has_ctype()) { ::google::protobuf::internal::WireFormatLite::WriteEnum( 1, this->ctype(), output); } - + // optional bool packed = 2; - if (_has_bit(1)) { + if (has_packed()) { ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->packed(), output); } - + // optional bool deprecated = 3 [default = false]; - if (_has_bit(2)) { + if (has_deprecated()) { ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output); } - + + // optional bool lazy = 5 [default = false]; + if (has_lazy()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(5, this->lazy(), output); + } + // optional string experimental_map_key = 9; - if (_has_bit(3)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_experimental_map_key()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->experimental_map_key().data(), this->experimental_map_key().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "experimental_map_key"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 9, this->experimental_map_key(), output); } - + + // optional bool weak = 10 [default = false]; + if (has_weak()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->weak(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 999, this->uninterpreted_option(i), output); } - + // Extension range [1000, 536870912) _extensions_.SerializeWithCachedSizes( 1000, 536870912, output); - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.FieldOptions) } ::google::protobuf::uint8* FieldOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions) // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; - if (_has_bit(0)) { + if (has_ctype()) { target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( 1, this->ctype(), target); } - + // optional bool packed = 2; - if (_has_bit(1)) { + if (has_packed()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->packed(), target); } - + // optional bool deprecated = 3 [default = false]; - if (_has_bit(2)) { + if (has_deprecated()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target); } - + + // optional bool lazy = 5 [default = false]; + if (has_lazy()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->lazy(), target); + } + // optional string experimental_map_key = 9; - if (_has_bit(3)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_experimental_map_key()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->experimental_map_key().data(), this->experimental_map_key().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "experimental_map_key"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 9, this->experimental_map_key(), target); } - + + // optional bool weak = 10 [default = false]; + if (has_weak()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->weak(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 999, this->uninterpreted_option(i), target); } - + // Extension range [1000, 536870912) target = _extensions_.SerializeWithCachedSizesToArray( 1000, 536870912, target); - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions) return target; } int FieldOptions::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; if (has_ctype()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::EnumSize(this->ctype()); } - + // optional bool packed = 2; if (has_packed()) { total_size += 1 + 1; } - + + // optional bool lazy = 5 [default = false]; + if (has_lazy()) { + total_size += 1 + 1; + } + // optional bool deprecated = 3 [default = false]; if (has_deprecated()) { total_size += 1 + 1; } - + // optional string experimental_map_key = 9; if (has_experimental_map_key()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->experimental_map_key()); } - + + // optional bool weak = 10 [default = false]; + if (has_weak()) { + total_size += 1 + 1; + } + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); @@ -5334,9 +6413,9 @@ int FieldOptions::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } - + total_size += _extensions_.ByteSize(); - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -5364,18 +6443,24 @@ void FieldOptions::MergeFrom(const FieldOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_ctype()) { set_ctype(from.ctype()); } - if (from._has_bit(1)) { + if (from.has_packed()) { set_packed(from.packed()); } - if (from._has_bit(2)) { + if (from.has_lazy()) { + set_lazy(from.lazy()); + } + if (from.has_deprecated()) { set_deprecated(from.deprecated()); } - if (from._has_bit(3)) { + if (from.has_experimental_map_key()) { set_experimental_map_key(from.experimental_map_key()); } + if (from.has_weak()) { + set_weak(from.weak()); + } } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); @@ -5394,11 +6479,9 @@ void FieldOptions::CopyFrom(const FieldOptions& from) { } bool FieldOptions::IsInitialized() const { - - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } - + + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!_extensions_.IsInitialized()) return false; return true; } @@ -5406,8 +6489,10 @@ void FieldOptions::Swap(FieldOptions* other) { if (other != this) { std::swap(ctype_, other->ctype_); std::swap(packed_, other->packed_); + std::swap(lazy_, other->lazy_); std::swap(deprecated_, other->deprecated_); std::swap(experimental_map_key_, other->experimental_map_key_); + std::swap(weak_, other->weak_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -5428,12 +6513,15 @@ void FieldOptions::Swap(FieldOptions* other) { // =================================================================== #ifndef _MSC_VER +const int EnumOptions::kAllowAliasFieldNumber; +const int EnumOptions::kDeprecatedFieldNumber; const int EnumOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER EnumOptions::EnumOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.EnumOptions) } void EnumOptions::InitAsDefaultInstance() { @@ -5443,14 +6531,18 @@ EnumOptions::EnumOptions(const EnumOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumOptions) } void EnumOptions::SharedCtor() { _cached_size_ = 0; + allow_alias_ = false; + deprecated_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } EnumOptions::~EnumOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumOptions) SharedDtor(); } @@ -5470,7 +6562,8 @@ const ::google::protobuf::Descriptor* EnumOptions::descriptor() { } const EnumOptions& EnumOptions::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } EnumOptions* EnumOptions::default_instance_ = NULL; @@ -5481,37 +6574,85 @@ EnumOptions* EnumOptions::New() const { void EnumOptions::Clear() { _extensions_.Clear(); - uninterpreted_option_.Clear(); +#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ + &reinterpret_cast(16)->f) - \ + reinterpret_cast(16)) + +#define ZR_(first, last) do { \ + size_t f = OFFSET_OF_FIELD_(first); \ + size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ + ::memset(&first, 0, n); \ + } while (0) + + ZR_(allow_alias_, deprecated_); + +#undef OFFSET_OF_FIELD_ +#undef ZR_ + + uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); } bool EnumOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.EnumOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional bool allow_alias = 2; + case 2: { + if (tag == 16) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &allow_alias_))); + set_has_allow_alias(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(24)) goto parse_deprecated; + break; + } + + // optional bool deprecated = 3 [default = false]; + case 3: { + if (tag == 24) { + parse_deprecated: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + break; + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -5524,51 +6665,92 @@ bool EnumOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.EnumOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.EnumOptions) + return false; #undef DO_ } void EnumOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.EnumOptions) + // optional bool allow_alias = 2; + if (has_allow_alias()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->allow_alias(), output); + } + + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 999, this->uninterpreted_option(i), output); } - + // Extension range [1000, 536870912) _extensions_.SerializeWithCachedSizes( 1000, 536870912, output); - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.EnumOptions) } ::google::protobuf::uint8* EnumOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumOptions) + // optional bool allow_alias = 2; + if (has_allow_alias()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->allow_alias(), target); + } + + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 999, this->uninterpreted_option(i), target); } - + // Extension range [1000, 536870912) target = _extensions_.SerializeWithCachedSizesToArray( 1000, 536870912, target); - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumOptions) return target; } int EnumOptions::ByteSize() const { int total_size = 0; - + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional bool allow_alias = 2; + if (has_allow_alias()) { + total_size += 1 + 1; + } + + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + total_size += 1 + 1; + } + + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { @@ -5576,9 +6758,9 @@ int EnumOptions::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } - + total_size += _extensions_.ByteSize(); - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -5605,6 +6787,14 @@ void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) { void EnumOptions::MergeFrom(const EnumOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_allow_alias()) { + set_allow_alias(from.allow_alias()); + } + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } + } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); } @@ -5622,16 +6812,16 @@ void EnumOptions::CopyFrom(const EnumOptions& from) { } bool EnumOptions::IsInitialized() const { - - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } - + + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!_extensions_.IsInitialized()) return false; return true; } void EnumOptions::Swap(EnumOptions* other) { if (other != this) { + std::swap(allow_alias_, other->allow_alias_); + std::swap(deprecated_, other->deprecated_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -5652,12 +6842,14 @@ void EnumOptions::Swap(EnumOptions* other) { // =================================================================== #ifndef _MSC_VER +const int EnumValueOptions::kDeprecatedFieldNumber; const int EnumValueOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER EnumValueOptions::EnumValueOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.EnumValueOptions) } void EnumValueOptions::InitAsDefaultInstance() { @@ -5667,14 +6859,17 @@ EnumValueOptions::EnumValueOptions(const EnumValueOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueOptions) } void EnumValueOptions::SharedCtor() { _cached_size_ = 0; + deprecated_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } EnumValueOptions::~EnumValueOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumValueOptions) SharedDtor(); } @@ -5694,7 +6889,8 @@ const ::google::protobuf::Descriptor* EnumValueOptions::descriptor() { } const EnumValueOptions& EnumValueOptions::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } EnumValueOptions* EnumValueOptions::default_instance_ = NULL; @@ -5705,6 +6901,7 @@ EnumValueOptions* EnumValueOptions::New() const { void EnumValueOptions::Clear() { _extensions_.Clear(); + deprecated_ = false; uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -5712,30 +6909,48 @@ void EnumValueOptions::Clear() { bool EnumValueOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.EnumValueOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional bool deprecated = 1 [default = false]; + case 1: { + if (tag == 8) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + break; + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -5748,51 +6963,77 @@ bool EnumValueOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.EnumValueOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.EnumValueOptions) + return false; #undef DO_ } void EnumValueOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.EnumValueOptions) + // optional bool deprecated = 1 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->deprecated(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 999, this->uninterpreted_option(i), output); } - + // Extension range [1000, 536870912) _extensions_.SerializeWithCachedSizes( 1000, 536870912, output); - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValueOptions) } ::google::protobuf::uint8* EnumValueOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueOptions) + // optional bool deprecated = 1 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->deprecated(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 999, this->uninterpreted_option(i), target); } - + // Extension range [1000, 536870912) target = _extensions_.SerializeWithCachedSizesToArray( 1000, 536870912, target); - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueOptions) return target; } int EnumValueOptions::ByteSize() const { int total_size = 0; - + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional bool deprecated = 1 [default = false]; + if (has_deprecated()) { + total_size += 1 + 1; + } + + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { @@ -5800,9 +7041,9 @@ int EnumValueOptions::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } - + total_size += _extensions_.ByteSize(); - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -5829,6 +7070,11 @@ void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) { void EnumValueOptions::MergeFrom(const EnumValueOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } + } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); } @@ -5846,16 +7092,15 @@ void EnumValueOptions::CopyFrom(const EnumValueOptions& from) { } bool EnumValueOptions::IsInitialized() const { - - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } - + + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!_extensions_.IsInitialized()) return false; return true; } void EnumValueOptions::Swap(EnumValueOptions* other) { if (other != this) { + std::swap(deprecated_, other->deprecated_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -5876,12 +7121,14 @@ void EnumValueOptions::Swap(EnumValueOptions* other) { // =================================================================== #ifndef _MSC_VER +const int ServiceOptions::kDeprecatedFieldNumber; const int ServiceOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER ServiceOptions::ServiceOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.ServiceOptions) } void ServiceOptions::InitAsDefaultInstance() { @@ -5891,14 +7138,17 @@ ServiceOptions::ServiceOptions(const ServiceOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceOptions) } void ServiceOptions::SharedCtor() { _cached_size_ = 0; + deprecated_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } ServiceOptions::~ServiceOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.ServiceOptions) SharedDtor(); } @@ -5918,7 +7168,8 @@ const ::google::protobuf::Descriptor* ServiceOptions::descriptor() { } const ServiceOptions& ServiceOptions::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } ServiceOptions* ServiceOptions::default_instance_ = NULL; @@ -5929,6 +7180,7 @@ ServiceOptions* ServiceOptions::New() const { void ServiceOptions::Clear() { _extensions_.Clear(); + deprecated_ = false; uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -5936,30 +7188,48 @@ void ServiceOptions::Clear() { bool ServiceOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.ServiceOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional bool deprecated = 33 [default = false]; + case 33: { + if (tag == 264) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + break; + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -5972,51 +7242,77 @@ bool ServiceOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.ServiceOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.ServiceOptions) + return false; #undef DO_ } void ServiceOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.ServiceOptions) + // optional bool deprecated = 33 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(33, this->deprecated(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 999, this->uninterpreted_option(i), output); } - + // Extension range [1000, 536870912) _extensions_.SerializeWithCachedSizes( 1000, 536870912, output); - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.ServiceOptions) } ::google::protobuf::uint8* ServiceOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceOptions) + // optional bool deprecated = 33 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(33, this->deprecated(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 999, this->uninterpreted_option(i), target); } - + // Extension range [1000, 536870912) target = _extensions_.SerializeWithCachedSizesToArray( 1000, 536870912, target); - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceOptions) return target; } int ServiceOptions::ByteSize() const { int total_size = 0; - + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional bool deprecated = 33 [default = false]; + if (has_deprecated()) { + total_size += 2 + 1; + } + + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { @@ -6024,9 +7320,9 @@ int ServiceOptions::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } - + total_size += _extensions_.ByteSize(); - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -6053,6 +7349,11 @@ void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) { void ServiceOptions::MergeFrom(const ServiceOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } + } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); } @@ -6070,16 +7371,15 @@ void ServiceOptions::CopyFrom(const ServiceOptions& from) { } bool ServiceOptions::IsInitialized() const { - - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } - + + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!_extensions_.IsInitialized()) return false; return true; } void ServiceOptions::Swap(ServiceOptions* other) { if (other != this) { + std::swap(deprecated_, other->deprecated_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -6100,12 +7400,14 @@ void ServiceOptions::Swap(ServiceOptions* other) { // =================================================================== #ifndef _MSC_VER +const int MethodOptions::kDeprecatedFieldNumber; const int MethodOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER MethodOptions::MethodOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.MethodOptions) } void MethodOptions::InitAsDefaultInstance() { @@ -6115,14 +7417,17 @@ MethodOptions::MethodOptions(const MethodOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodOptions) } void MethodOptions::SharedCtor() { _cached_size_ = 0; + deprecated_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } MethodOptions::~MethodOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.MethodOptions) SharedDtor(); } @@ -6142,7 +7447,8 @@ const ::google::protobuf::Descriptor* MethodOptions::descriptor() { } const MethodOptions& MethodOptions::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } MethodOptions* MethodOptions::default_instance_ = NULL; @@ -6153,6 +7459,7 @@ MethodOptions* MethodOptions::New() const { void MethodOptions::Clear() { _extensions_.Clear(); + deprecated_ = false; uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -6160,30 +7467,48 @@ void MethodOptions::Clear() { bool MethodOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.MethodOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional bool deprecated = 33 [default = false]; + case 33: { + if (tag == 264) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + break; + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -6196,51 +7521,77 @@ bool MethodOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.MethodOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.MethodOptions) + return false; #undef DO_ } void MethodOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.MethodOptions) + // optional bool deprecated = 33 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(33, this->deprecated(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 999, this->uninterpreted_option(i), output); } - + // Extension range [1000, 536870912) _extensions_.SerializeWithCachedSizes( 1000, 536870912, output); - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.MethodOptions) } ::google::protobuf::uint8* MethodOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodOptions) + // optional bool deprecated = 33 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(33, this->deprecated(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 999, this->uninterpreted_option(i), target); } - + // Extension range [1000, 536870912) target = _extensions_.SerializeWithCachedSizesToArray( 1000, 536870912, target); - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodOptions) return target; } int MethodOptions::ByteSize() const { int total_size = 0; - + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional bool deprecated = 33 [default = false]; + if (has_deprecated()) { + total_size += 2 + 1; + } + + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { @@ -6248,9 +7599,9 @@ int MethodOptions::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } - + total_size += _extensions_.ByteSize(); - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -6277,6 +7628,11 @@ void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) { void MethodOptions::MergeFrom(const MethodOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } + } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); } @@ -6294,16 +7650,15 @@ void MethodOptions::CopyFrom(const MethodOptions& from) { } bool MethodOptions::IsInitialized() const { - - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } - + + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!_extensions_.IsInitialized()) return false; return true; } void MethodOptions::Swap(MethodOptions* other) { if (other != this) { + std::swap(deprecated_, other->deprecated_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -6323,7 +7678,6 @@ void MethodOptions::Swap(MethodOptions* other) { // =================================================================== -const ::std::string UninterpretedOption_NamePart::_default_name_part_; #ifndef _MSC_VER const int UninterpretedOption_NamePart::kNamePartFieldNumber; const int UninterpretedOption_NamePart::kIsExtensionFieldNumber; @@ -6332,6 +7686,7 @@ const int UninterpretedOption_NamePart::kIsExtensionFieldNumber; UninterpretedOption_NamePart::UninterpretedOption_NamePart() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption.NamePart) } void UninterpretedOption_NamePart::InitAsDefaultInstance() { @@ -6341,21 +7696,24 @@ UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOp : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption.NamePart) } void UninterpretedOption_NamePart::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_part_ = const_cast< ::std::string*>(&_default_name_part_); + name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); is_extension_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } UninterpretedOption_NamePart::~UninterpretedOption_NamePart() { + // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption.NamePart) SharedDtor(); } void UninterpretedOption_NamePart::SharedDtor() { - if (name_part_ != &_default_name_part_) { + if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_part_; } if (this != default_instance_) { @@ -6373,7 +7731,8 @@ const ::google::protobuf::Descriptor* UninterpretedOption_NamePart::descriptor() } const UninterpretedOption_NamePart& UninterpretedOption_NamePart::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } UninterpretedOption_NamePart* UninterpretedOption_NamePart::default_instance_ = NULL; @@ -6383,9 +7742,9 @@ UninterpretedOption_NamePart* UninterpretedOption_NamePart::New() const { } void UninterpretedOption_NamePart::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_part_ != &_default_name_part_) { + if (_has_bits_[0 / 32] & 3) { + if (has_name_part()) { + if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_part_->clear(); } } @@ -6397,47 +7756,51 @@ void UninterpretedOption_NamePart::Clear() { bool UninterpretedOption_NamePart::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.UninterpretedOption.NamePart) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // required string name_part = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name_part())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name_part().data(), this->name_part().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name_part"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(16)) goto parse_is_extension; break; } - + // required bool is_extension = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 16) { parse_is_extension: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &is_extension_))); - _set_bit(1); + set_has_is_extension(); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -6445,59 +7808,70 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.UninterpretedOption.NamePart) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.UninterpretedOption.NamePart) + return false; #undef DO_ } void UninterpretedOption_NamePart::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.UninterpretedOption.NamePart) // required string name_part = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name_part()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name_part().data(), this->name_part().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name_part"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name_part(), output); } - + // required bool is_extension = 2; - if (_has_bit(1)) { + if (has_is_extension()) { ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_extension(), output); } - + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.UninterpretedOption.NamePart) } ::google::protobuf::uint8* UninterpretedOption_NamePart::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption.NamePart) // required string name_part = 1; - if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_name_part()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name_part().data(), this->name_part().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name_part"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name_part(), target); } - + // required bool is_extension = 2; - if (_has_bit(1)) { + if (has_is_extension()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_extension(), target); } - + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption.NamePart) return target; } int UninterpretedOption_NamePart::ByteSize() const { int total_size = 0; - + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // required string name_part = 1; if (has_name_part()) { @@ -6505,12 +7879,12 @@ int UninterpretedOption_NamePart::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->name_part()); } - + // required bool is_extension = 2; if (has_is_extension()) { total_size += 1 + 1; } - + } if (!unknown_fields().empty()) { total_size += @@ -6538,10 +7912,10 @@ void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name_part()) { set_name_part(from.name_part()); } - if (from._has_bit(1)) { + if (from.has_is_extension()) { set_is_extension(from.is_extension()); } } @@ -6562,7 +7936,7 @@ void UninterpretedOption_NamePart::CopyFrom(const UninterpretedOption_NamePart& bool UninterpretedOption_NamePart::IsInitialized() const { if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; - + return true; } @@ -6587,8 +7961,6 @@ void UninterpretedOption_NamePart::Swap(UninterpretedOption_NamePart* other) { // ------------------------------------------------------------------- -const ::std::string UninterpretedOption::_default_identifier_value_; -const ::std::string UninterpretedOption::_default_string_value_; #ifndef _MSC_VER const int UninterpretedOption::kNameFieldNumber; const int UninterpretedOption::kIdentifierValueFieldNumber; @@ -6596,11 +7968,13 @@ const int UninterpretedOption::kPositiveIntValueFieldNumber; const int UninterpretedOption::kNegativeIntValueFieldNumber; const int UninterpretedOption::kDoubleValueFieldNumber; const int UninterpretedOption::kStringValueFieldNumber; +const int UninterpretedOption::kAggregateValueFieldNumber; #endif // !_MSC_VER UninterpretedOption::UninterpretedOption() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption) } void UninterpretedOption::InitAsDefaultInstance() { @@ -6610,29 +7984,36 @@ UninterpretedOption::UninterpretedOption(const UninterpretedOption& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption) } void UninterpretedOption::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - identifier_value_ = const_cast< ::std::string*>(&_default_identifier_value_); + identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); positive_int_value_ = GOOGLE_ULONGLONG(0); negative_int_value_ = GOOGLE_LONGLONG(0); double_value_ = 0; - string_value_ = const_cast< ::std::string*>(&_default_string_value_); + string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } UninterpretedOption::~UninterpretedOption() { + // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption) SharedDtor(); } void UninterpretedOption::SharedDtor() { - if (identifier_value_ != &_default_identifier_value_) { + if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete identifier_value_; } - if (string_value_ != &_default_string_value_) { + if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete string_value_; } + if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete aggregate_value_; + } if (this != default_instance_) { } } @@ -6648,7 +8029,8 @@ const ::google::protobuf::Descriptor* UninterpretedOption::descriptor() { } const UninterpretedOption& UninterpretedOption::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; } UninterpretedOption* UninterpretedOption::default_instance_ = NULL; @@ -6658,21 +8040,38 @@ UninterpretedOption* UninterpretedOption::New() const { } void UninterpretedOption::Clear() { - if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { - if (_has_bit(1)) { - if (identifier_value_ != &_default_identifier_value_) { +#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ + &reinterpret_cast(16)->f) - \ + reinterpret_cast(16)) + +#define ZR_(first, last) do { \ + size_t f = OFFSET_OF_FIELD_(first); \ + size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ + ::memset(&first, 0, n); \ + } while (0) + + if (_has_bits_[0 / 32] & 126) { + ZR_(positive_int_value_, double_value_); + if (has_identifier_value()) { + if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { identifier_value_->clear(); } } - positive_int_value_ = GOOGLE_ULONGLONG(0); - negative_int_value_ = GOOGLE_LONGLONG(0); - double_value_ = 0; - if (_has_bit(5)) { - if (string_value_ != &_default_string_value_) { + if (has_string_value()) { + if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { string_value_->clear(); } } + if (has_aggregate_value()) { + if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + aggregate_value_->clear(); + } + } } + +#undef OFFSET_OF_FIELD_ +#undef ZR_ + name_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -6680,109 +8079,126 @@ void UninterpretedOption::Clear() { bool UninterpretedOption::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.UninterpretedOption) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_name: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_name())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_name; if (input->ExpectTag(26)) goto parse_identifier_value; break; } - + // optional string identifier_value = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_identifier_value: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_identifier_value())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->identifier_value().data(), this->identifier_value().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "identifier_value"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(32)) goto parse_positive_int_value; break; } - + // optional uint64 positive_int_value = 4; case 4: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 32) { parse_positive_int_value: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>( input, &positive_int_value_))); - _set_bit(2); + set_has_positive_int_value(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(40)) goto parse_negative_int_value; break; } - + // optional int64 negative_int_value = 5; case 5: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 40) { parse_negative_int_value: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( input, &negative_int_value_))); - _set_bit(3); + set_has_negative_int_value(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(49)) goto parse_double_value; break; } - + // optional double double_value = 6; case 6: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + if (tag == 49) { parse_double_value: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( input, &double_value_))); - _set_bit(4); + set_has_double_value(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(58)) goto parse_string_value; break; } - + // optional bytes string_value = 7; case 7: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 58) { parse_string_value: DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( input, this->mutable_string_value())); } else { - goto handle_uninterpreted; + goto handle_unusual; + } + if (input->ExpectTag(66)) goto parse_aggregate_value; + break; + } + + // optional string aggregate_value = 8; + case 8: { + if (tag == 66) { + parse_aggregate_value: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_aggregate_value())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->aggregate_value().data(), this->aggregate_value().length(), + ::google::protobuf::internal::WireFormat::PARSE, + "aggregate_value"); + } else { + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } - + default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -6790,105 +8206,137 @@ bool UninterpretedOption::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.UninterpretedOption) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.UninterpretedOption) + return false; #undef DO_ } void UninterpretedOption::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.UninterpretedOption) // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; for (int i = 0; i < this->name_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 2, this->name(i), output); } - + // optional string identifier_value = 3; - if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_identifier_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->identifier_value().data(), this->identifier_value().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "identifier_value"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 3, this->identifier_value(), output); } - + // optional uint64 positive_int_value = 4; - if (_has_bit(2)) { + if (has_positive_int_value()) { ::google::protobuf::internal::WireFormatLite::WriteUInt64(4, this->positive_int_value(), output); } - + // optional int64 negative_int_value = 5; - if (_has_bit(3)) { + if (has_negative_int_value()) { ::google::protobuf::internal::WireFormatLite::WriteInt64(5, this->negative_int_value(), output); } - + // optional double double_value = 6; - if (_has_bit(4)) { + if (has_double_value()) { ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->double_value(), output); } - + // optional bytes string_value = 7; - if (_has_bit(5)) { - ::google::protobuf::internal::WireFormatLite::WriteBytes( + if (has_string_value()) { + ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased( 7, this->string_value(), output); } - + + // optional string aggregate_value = 8; + if (has_aggregate_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->aggregate_value().data(), this->aggregate_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "aggregate_value"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 8, this->aggregate_value(), output); + } + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.UninterpretedOption) } ::google::protobuf::uint8* UninterpretedOption::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption) // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; for (int i = 0; i < this->name_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 2, this->name(i), target); } - + // optional string identifier_value = 3; - if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + if (has_identifier_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->identifier_value().data(), this->identifier_value().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "identifier_value"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 3, this->identifier_value(), target); } - + // optional uint64 positive_int_value = 4; - if (_has_bit(2)) { + if (has_positive_int_value()) { target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(4, this->positive_int_value(), target); } - + // optional int64 negative_int_value = 5; - if (_has_bit(3)) { + if (has_negative_int_value()) { target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(5, this->negative_int_value(), target); } - + // optional double double_value = 6; - if (_has_bit(4)) { + if (has_double_value()) { target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->double_value(), target); } - + // optional bytes string_value = 7; - if (_has_bit(5)) { + if (has_string_value()) { target = ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( 7, this->string_value(), target); } - + + // optional string aggregate_value = 8; + if (has_aggregate_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->aggregate_value().data(), this->aggregate_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "aggregate_value"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 8, this->aggregate_value(), target); + } + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption) return target; } int UninterpretedOption::ByteSize() const { int total_size = 0; - + if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { // optional string identifier_value = 3; if (has_identifier_value()) { @@ -6896,33 +8344,40 @@ int UninterpretedOption::ByteSize() const { ::google::protobuf::internal::WireFormatLite::StringSize( this->identifier_value()); } - + // optional uint64 positive_int_value = 4; if (has_positive_int_value()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::UInt64Size( this->positive_int_value()); } - + // optional int64 negative_int_value = 5; if (has_negative_int_value()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::Int64Size( this->negative_int_value()); } - + // optional double double_value = 6; if (has_double_value()) { total_size += 1 + 8; } - + // optional bytes string_value = 7; if (has_string_value()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::BytesSize( this->string_value()); } - + + // optional string aggregate_value = 8; + if (has_aggregate_value()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->aggregate_value()); + } + } // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; total_size += 1 * this->name_size(); @@ -6931,7 +8386,7 @@ int UninterpretedOption::ByteSize() const { ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->name(i)); } - + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -6959,21 +8414,24 @@ void UninterpretedOption::MergeFrom(const UninterpretedOption& from) { GOOGLE_CHECK_NE(&from, this); name_.MergeFrom(from.name_); if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) { - if (from._has_bit(1)) { + if (from.has_identifier_value()) { set_identifier_value(from.identifier_value()); } - if (from._has_bit(2)) { + if (from.has_positive_int_value()) { set_positive_int_value(from.positive_int_value()); } - if (from._has_bit(3)) { + if (from.has_negative_int_value()) { set_negative_int_value(from.negative_int_value()); } - if (from._has_bit(4)) { + if (from.has_double_value()) { set_double_value(from.double_value()); } - if (from._has_bit(5)) { + if (from.has_string_value()) { set_string_value(from.string_value()); } + if (from.has_aggregate_value()) { + set_aggregate_value(from.aggregate_value()); + } } mutable_unknown_fields()->MergeFrom(from.unknown_fields()); } @@ -6991,10 +8449,8 @@ void UninterpretedOption::CopyFrom(const UninterpretedOption& from) { } bool UninterpretedOption::IsInitialized() const { - - for (int i = 0; i < name_size(); i++) { - if (!this->name(i).IsInitialized()) return false; - } + + if (!::google::protobuf::internal::AllAreInitialized(this->name())) return false; return true; } @@ -7006,6 +8462,7 @@ void UninterpretedOption::Swap(UninterpretedOption* other) { std::swap(negative_int_value_, other->negative_int_value_); std::swap(double_value_, other->double_value_); std::swap(string_value_, other->string_value_); + std::swap(aggregate_value_, other->aggregate_value_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); std::swap(_cached_size_, other->_cached_size_); @@ -7021,6 +8478,655 @@ void UninterpretedOption::Swap(UninterpretedOption* other) { } +// =================================================================== + +#ifndef _MSC_VER +const int SourceCodeInfo_Location::kPathFieldNumber; +const int SourceCodeInfo_Location::kSpanFieldNumber; +const int SourceCodeInfo_Location::kLeadingCommentsFieldNumber; +const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber; +#endif // !_MSC_VER + +SourceCodeInfo_Location::SourceCodeInfo_Location() + : ::google::protobuf::Message() { + SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo.Location) +} + +void SourceCodeInfo_Location::InitAsDefaultInstance() { +} + +SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo.Location) +} + +void SourceCodeInfo_Location::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); + _cached_size_ = 0; + leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +SourceCodeInfo_Location::~SourceCodeInfo_Location() { + // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo.Location) + SharedDtor(); +} + +void SourceCodeInfo_Location::SharedDtor() { + if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete leading_comments_; + } + if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete trailing_comments_; + } + if (this != default_instance_) { + } +} + +void SourceCodeInfo_Location::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* SourceCodeInfo_Location::descriptor() { + protobuf_AssignDescriptorsOnce(); + return SourceCodeInfo_Location_descriptor_; +} + +const SourceCodeInfo_Location& SourceCodeInfo_Location::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +SourceCodeInfo_Location* SourceCodeInfo_Location::default_instance_ = NULL; + +SourceCodeInfo_Location* SourceCodeInfo_Location::New() const { + return new SourceCodeInfo_Location; +} + +void SourceCodeInfo_Location::Clear() { + if (_has_bits_[0 / 32] & 12) { + if (has_leading_comments()) { + if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + leading_comments_->clear(); + } + } + if (has_trailing_comments()) { + if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + trailing_comments_->clear(); + } + } + } + path_.Clear(); + span_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool SourceCodeInfo_Location::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:google.protobuf.SourceCodeInfo.Location) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated int32 path = 1 [packed = true]; + case 1: { + if (tag == 10) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, this->mutable_path()))); + } else if (tag == 8) { + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + 1, 10, input, this->mutable_path()))); + } else { + goto handle_unusual; + } + if (input->ExpectTag(18)) goto parse_span; + break; + } + + // repeated int32 span = 2 [packed = true]; + case 2: { + if (tag == 18) { + parse_span: + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, this->mutable_span()))); + } else if (tag == 16) { + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + 1, 18, input, this->mutable_span()))); + } else { + goto handle_unusual; + } + if (input->ExpectTag(26)) goto parse_leading_comments; + break; + } + + // optional string leading_comments = 3; + case 3: { + if (tag == 26) { + parse_leading_comments: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_leading_comments())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->leading_comments().data(), this->leading_comments().length(), + ::google::protobuf::internal::WireFormat::PARSE, + "leading_comments"); + } else { + goto handle_unusual; + } + if (input->ExpectTag(34)) goto parse_trailing_comments; + break; + } + + // optional string trailing_comments = 4; + case 4: { + if (tag == 34) { + parse_trailing_comments: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_trailing_comments())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->trailing_comments().data(), this->trailing_comments().length(), + ::google::protobuf::internal::WireFormat::PARSE, + "trailing_comments"); + } else { + goto handle_unusual; + } + if (input->ExpectAtEnd()) goto success; + break; + } + + default: { + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.SourceCodeInfo.Location) + return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.SourceCodeInfo.Location) + return false; +#undef DO_ +} + +void SourceCodeInfo_Location::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.SourceCodeInfo.Location) + // repeated int32 path = 1 [packed = true]; + if (this->path_size() > 0) { + ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); + output->WriteVarint32(_path_cached_byte_size_); + } + for (int i = 0; i < this->path_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag( + this->path(i), output); + } + + // repeated int32 span = 2 [packed = true]; + if (this->span_size() > 0) { + ::google::protobuf::internal::WireFormatLite::WriteTag(2, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); + output->WriteVarint32(_span_cached_byte_size_); + } + for (int i = 0; i < this->span_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag( + this->span(i), output); + } + + // optional string leading_comments = 3; + if (has_leading_comments()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->leading_comments().data(), this->leading_comments().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "leading_comments"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 3, this->leading_comments(), output); + } + + // optional string trailing_comments = 4; + if (has_trailing_comments()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->trailing_comments().data(), this->trailing_comments().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "trailing_comments"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 4, this->trailing_comments(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } + // @@protoc_insertion_point(serialize_end:google.protobuf.SourceCodeInfo.Location) +} + +::google::protobuf::uint8* SourceCodeInfo_Location::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo.Location) + // repeated int32 path = 1 [packed = true]; + if (this->path_size() > 0) { + target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( + 1, + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + target); + target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( + _path_cached_byte_size_, target); + } + for (int i = 0; i < this->path_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32NoTagToArray(this->path(i), target); + } + + // repeated int32 span = 2 [packed = true]; + if (this->span_size() > 0) { + target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( + 2, + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + target); + target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( + _span_cached_byte_size_, target); + } + for (int i = 0; i < this->span_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32NoTagToArray(this->span(i), target); + } + + // optional string leading_comments = 3; + if (has_leading_comments()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->leading_comments().data(), this->leading_comments().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "leading_comments"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 3, this->leading_comments(), target); + } + + // optional string trailing_comments = 4; + if (has_trailing_comments()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->trailing_comments().data(), this->trailing_comments().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "trailing_comments"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 4, this->trailing_comments(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo.Location) + return target; +} + +int SourceCodeInfo_Location::ByteSize() const { + int total_size = 0; + + if (_has_bits_[2 / 32] & (0xffu << (2 % 32))) { + // optional string leading_comments = 3; + if (has_leading_comments()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->leading_comments()); + } + + // optional string trailing_comments = 4; + if (has_trailing_comments()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->trailing_comments()); + } + + } + // repeated int32 path = 1 [packed = true]; + { + int data_size = 0; + for (int i = 0; i < this->path_size(); i++) { + data_size += ::google::protobuf::internal::WireFormatLite:: + Int32Size(this->path(i)); + } + if (data_size > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size(data_size); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _path_cached_byte_size_ = data_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + total_size += data_size; + } + + // repeated int32 span = 2 [packed = true]; + { + int data_size = 0; + for (int i = 0; i < this->span_size(); i++) { + data_size += ::google::protobuf::internal::WireFormatLite:: + Int32Size(this->span(i)); + } + if (data_size > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size(data_size); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _span_cached_byte_size_ = data_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + total_size += data_size; + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const SourceCodeInfo_Location* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) { + GOOGLE_CHECK_NE(&from, this); + path_.MergeFrom(from.path_); + span_.MergeFrom(from.span_); + if (from._has_bits_[2 / 32] & (0xffu << (2 % 32))) { + if (from.has_leading_comments()) { + set_leading_comments(from.leading_comments()); + } + if (from.has_trailing_comments()) { + set_trailing_comments(from.trailing_comments()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void SourceCodeInfo_Location::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void SourceCodeInfo_Location::CopyFrom(const SourceCodeInfo_Location& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SourceCodeInfo_Location::IsInitialized() const { + + return true; +} + +void SourceCodeInfo_Location::Swap(SourceCodeInfo_Location* other) { + if (other != this) { + path_.Swap(&other->path_); + span_.Swap(&other->span_); + std::swap(leading_comments_, other->leading_comments_); + std::swap(trailing_comments_, other->trailing_comments_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata SourceCodeInfo_Location::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = SourceCodeInfo_Location_descriptor_; + metadata.reflection = SourceCodeInfo_Location_reflection_; + return metadata; +} + + +// ------------------------------------------------------------------- + +#ifndef _MSC_VER +const int SourceCodeInfo::kLocationFieldNumber; +#endif // !_MSC_VER + +SourceCodeInfo::SourceCodeInfo() + : ::google::protobuf::Message() { + SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo) +} + +void SourceCodeInfo::InitAsDefaultInstance() { +} + +SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo) +} + +void SourceCodeInfo::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +SourceCodeInfo::~SourceCodeInfo() { + // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo) + SharedDtor(); +} + +void SourceCodeInfo::SharedDtor() { + if (this != default_instance_) { + } +} + +void SourceCodeInfo::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* SourceCodeInfo::descriptor() { + protobuf_AssignDescriptorsOnce(); + return SourceCodeInfo_descriptor_; +} + +const SourceCodeInfo& SourceCodeInfo::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +SourceCodeInfo* SourceCodeInfo::default_instance_ = NULL; + +SourceCodeInfo* SourceCodeInfo::New() const { + return new SourceCodeInfo; +} + +void SourceCodeInfo::Clear() { + location_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool SourceCodeInfo::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:google.protobuf.SourceCodeInfo) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + case 1: { + if (tag == 10) { + parse_location: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_location())); + } else { + goto handle_unusual; + } + if (input->ExpectTag(10)) goto parse_location; + if (input->ExpectAtEnd()) goto success; + break; + } + + default: { + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.SourceCodeInfo) + return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.SourceCodeInfo) + return false; +#undef DO_ +} + +void SourceCodeInfo::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.SourceCodeInfo) + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + for (int i = 0; i < this->location_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->location(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } + // @@protoc_insertion_point(serialize_end:google.protobuf.SourceCodeInfo) +} + +::google::protobuf::uint8* SourceCodeInfo::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo) + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + for (int i = 0; i < this->location_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->location(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo) + return target; +} + +int SourceCodeInfo::ByteSize() const { + int total_size = 0; + + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + total_size += 1 * this->location_size(); + for (int i = 0; i < this->location_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->location(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const SourceCodeInfo* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) { + GOOGLE_CHECK_NE(&from, this); + location_.MergeFrom(from.location_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void SourceCodeInfo::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void SourceCodeInfo::CopyFrom(const SourceCodeInfo& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SourceCodeInfo::IsInitialized() const { + + return true; +} + +void SourceCodeInfo::Swap(SourceCodeInfo* other) { + if (other != this) { + location_.Swap(&other->location_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata SourceCodeInfo::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = SourceCodeInfo_descriptor_; + metadata.reflection = SourceCodeInfo_reflection_; + return metadata; +} + + // @@protoc_insertion_point(namespace_scope) } // namespace protobuf diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 2743b6f..d5221e7 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -8,21 +8,23 @@ #include -#if GOOGLE_PROTOBUF_VERSION < 2003000 +#if GOOGLE_PROTOBUF_VERSION < 2006000 #error This file was generated by a newer version of protoc which is #error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 2003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 2006000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is #error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif #include +#include #include #include -#include +#include +#include // @@protoc_insertion_point(includes) namespace google { @@ -38,6 +40,7 @@ class FileDescriptorProto; class DescriptorProto; class DescriptorProto_ExtensionRange; class FieldDescriptorProto; +class OneofDescriptorProto; class EnumDescriptorProto; class EnumValueDescriptorProto; class ServiceDescriptorProto; @@ -51,6 +54,8 @@ class ServiceOptions; class MethodOptions; class UninterpretedOption; class UninterpretedOption_NamePart; +class SourceCodeInfo; +class SourceCodeInfo_Location; enum FieldDescriptorProto_Type { FieldDescriptorProto_Type_TYPE_DOUBLE = 1, @@ -153,29 +158,29 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message public: FileDescriptorSet(); virtual ~FileDescriptorSet(); - + FileDescriptorSet(const FileDescriptorSet& from); - + inline FileDescriptorSet& operator=(const FileDescriptorSet& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const FileDescriptorSet& default_instance(); - + void Swap(FileDescriptorSet* other); - + // implements Message ---------------------------------------------- - + FileDescriptorSet* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -183,7 +188,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message void MergeFrom(const FileDescriptorSet& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -196,13 +201,12 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // repeated .google.protobuf.FileDescriptorProto file = 1; inline int file_size() const; inline void clear_file(); @@ -214,30 +218,19 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message file() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_file(); - + // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) private: + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static FileDescriptorSet* default_instance_; }; @@ -247,29 +240,29 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag public: FileDescriptorProto(); virtual ~FileDescriptorProto(); - + FileDescriptorProto(const FileDescriptorProto& from); - + inline FileDescriptorProto& operator=(const FileDescriptorProto& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const FileDescriptorProto& default_instance(); - + void Swap(FileDescriptorProto* other); - + // implements Message ---------------------------------------------- - + FileDescriptorProto* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -277,7 +270,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag void MergeFrom(const FileDescriptorProto& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -290,13 +283,12 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // optional string name = 1; inline bool has_name() const; inline void clear_name(); @@ -306,7 +298,9 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag inline void set_name(const char* value); inline void set_name(const char* value, size_t size); inline ::std::string* mutable_name(); - + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + // optional string package = 2; inline bool has_package() const; inline void clear_package(); @@ -316,7 +310,9 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag inline void set_package(const char* value); inline void set_package(const char* value, size_t size); inline ::std::string* mutable_package(); - + inline ::std::string* release_package(); + inline void set_allocated_package(::std::string* package); + // repeated string dependency = 3; inline int dependency_size() const; inline void clear_dependency(); @@ -332,7 +328,31 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag inline void add_dependency(const char* value, size_t size); inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const; inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency(); - + + // repeated int32 public_dependency = 10; + inline int public_dependency_size() const; + inline void clear_public_dependency(); + static const int kPublicDependencyFieldNumber = 10; + inline ::google::protobuf::int32 public_dependency(int index) const; + inline void set_public_dependency(int index, ::google::protobuf::int32 value); + inline void add_public_dependency(::google::protobuf::int32 value); + inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + public_dependency() const; + inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + mutable_public_dependency(); + + // repeated int32 weak_dependency = 11; + inline int weak_dependency_size() const; + inline void clear_weak_dependency(); + static const int kWeakDependencyFieldNumber = 11; + inline ::google::protobuf::int32 weak_dependency(int index) const; + inline void set_weak_dependency(int index, ::google::protobuf::int32 value); + inline void add_weak_dependency(::google::protobuf::int32 value); + inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + weak_dependency() const; + inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + mutable_weak_dependency(); + // repeated .google.protobuf.DescriptorProto message_type = 4; inline int message_type_size() const; inline void clear_message_type(); @@ -344,7 +364,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag message_type() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* mutable_message_type(); - + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; inline int enum_type_size() const; inline void clear_enum_type(); @@ -356,7 +376,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag enum_type() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* mutable_enum_type(); - + // repeated .google.protobuf.ServiceDescriptorProto service = 6; inline int service_size() const; inline void clear_service(); @@ -368,7 +388,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag service() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* mutable_service(); - + // repeated .google.protobuf.FieldDescriptorProto extension = 7; inline int extension_size() const; inline void clear_extension(); @@ -380,46 +400,55 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag extension() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_extension(); - + // optional .google.protobuf.FileOptions options = 8; inline bool has_options() const; inline void clear_options(); static const int kOptionsFieldNumber = 8; inline const ::google::protobuf::FileOptions& options() const; inline ::google::protobuf::FileOptions* mutable_options(); - + inline ::google::protobuf::FileOptions* release_options(); + inline void set_allocated_options(::google::protobuf::FileOptions* options); + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + inline bool has_source_code_info() const; + inline void clear_source_code_info(); + static const int kSourceCodeInfoFieldNumber = 9; + inline const ::google::protobuf::SourceCodeInfo& source_code_info() const; + inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info(); + inline ::google::protobuf::SourceCodeInfo* release_source_code_info(); + inline void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info); + // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_package(); + inline void clear_has_package(); + inline void set_has_options(); + inline void clear_has_options(); + inline void set_has_source_code_info(); + inline void clear_has_source_code_info(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::std::string* name_; - static const ::std::string _default_name_; ::std::string* package_; - static const ::std::string _default_package_; ::google::protobuf::RepeatedPtrField< ::std::string> dependency_; + ::google::protobuf::RepeatedField< ::google::protobuf::int32 > public_dependency_; + ::google::protobuf::RepeatedField< ::google::protobuf::int32 > weak_dependency_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > message_type_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto > service_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_; ::google::protobuf::FileOptions* options_; + ::google::protobuf::SourceCodeInfo* source_code_info_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static FileDescriptorProto* default_instance_; }; @@ -429,29 +458,29 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto public: DescriptorProto_ExtensionRange(); virtual ~DescriptorProto_ExtensionRange(); - + DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from); - + inline DescriptorProto_ExtensionRange& operator=(const DescriptorProto_ExtensionRange& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const DescriptorProto_ExtensionRange& default_instance(); - + void Swap(DescriptorProto_ExtensionRange* other); - + // implements Message ---------------------------------------------- - + DescriptorProto_ExtensionRange* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -459,7 +488,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto void MergeFrom(const DescriptorProto_ExtensionRange& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -472,51 +501,43 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // optional int32 start = 1; inline bool has_start() const; inline void clear_start(); static const int kStartFieldNumber = 1; inline ::google::protobuf::int32 start() const; inline void set_start(::google::protobuf::int32 value); - + // optional int32 end = 2; inline bool has_end() const; inline void clear_end(); static const int kEndFieldNumber = 2; inline ::google::protobuf::int32 end() const; inline void set_end(::google::protobuf::int32 value); - + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange) private: + inline void set_has_start(); + inline void clear_has_start(); + inline void set_has_end(); + inline void clear_has_end(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::int32 start_; ::google::protobuf::int32 end_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static DescriptorProto_ExtensionRange* default_instance_; }; @@ -526,29 +547,29 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { public: DescriptorProto(); virtual ~DescriptorProto(); - + DescriptorProto(const DescriptorProto& from); - + inline DescriptorProto& operator=(const DescriptorProto& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const DescriptorProto& default_instance(); - + void Swap(DescriptorProto* other); - + // implements Message ---------------------------------------------- - + DescriptorProto* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -556,7 +577,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { void MergeFrom(const DescriptorProto& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -569,15 +590,14 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + typedef DescriptorProto_ExtensionRange ExtensionRange; - + // accessors ------------------------------------------------------- - + // optional string name = 1; inline bool has_name() const; inline void clear_name(); @@ -587,7 +607,9 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { inline void set_name(const char* value); inline void set_name(const char* value, size_t size); inline ::std::string* mutable_name(); - + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + // repeated .google.protobuf.FieldDescriptorProto field = 2; inline int field_size() const; inline void clear_field(); @@ -599,7 +621,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { field() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_field(); - + // repeated .google.protobuf.FieldDescriptorProto extension = 6; inline int extension_size() const; inline void clear_extension(); @@ -611,7 +633,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { extension() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_extension(); - + // repeated .google.protobuf.DescriptorProto nested_type = 3; inline int nested_type_size() const; inline void clear_nested_type(); @@ -623,7 +645,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { nested_type() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* mutable_nested_type(); - + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; inline int enum_type_size() const; inline void clear_enum_type(); @@ -635,7 +657,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { enum_type() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* mutable_enum_type(); - + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; inline int extension_range_size() const; inline void clear_extension_range(); @@ -647,44 +669,51 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { extension_range() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* mutable_extension_range(); - + + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + inline int oneof_decl_size() const; + inline void clear_oneof_decl(); + static const int kOneofDeclFieldNumber = 8; + inline const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const; + inline ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index); + inline ::google::protobuf::OneofDescriptorProto* add_oneof_decl(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& + oneof_decl() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* + mutable_oneof_decl(); + // optional .google.protobuf.MessageOptions options = 7; inline bool has_options() const; inline void clear_options(); static const int kOptionsFieldNumber = 7; inline const ::google::protobuf::MessageOptions& options() const; inline ::google::protobuf::MessageOptions* mutable_options(); - + inline ::google::protobuf::MessageOptions* release_options(); + inline void set_allocated_options(::google::protobuf::MessageOptions* options); + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_options(); + inline void clear_has_options(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::std::string* name_; - static const ::std::string _default_name_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > field_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > nested_type_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto > oneof_decl_; ::google::protobuf::MessageOptions* options_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static DescriptorProto* default_instance_; }; @@ -694,29 +723,29 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa public: FieldDescriptorProto(); virtual ~FieldDescriptorProto(); - + FieldDescriptorProto(const FieldDescriptorProto& from); - + inline FieldDescriptorProto& operator=(const FieldDescriptorProto& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const FieldDescriptorProto& default_instance(); - + void Swap(FieldDescriptorProto* other); - + // implements Message ---------------------------------------------- - + FieldDescriptorProto* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -724,7 +753,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa void MergeFrom(const FieldDescriptorProto& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -737,11 +766,10 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + typedef FieldDescriptorProto_Type Type; static const Type TYPE_DOUBLE = FieldDescriptorProto_Type_TYPE_DOUBLE; static const Type TYPE_FLOAT = FieldDescriptorProto_Type_TYPE_FLOAT; @@ -781,7 +809,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa Type* value) { return FieldDescriptorProto_Type_Parse(name, value); } - + typedef FieldDescriptorProto_Label Label; static const Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL; static const Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED; @@ -806,9 +834,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa Label* value) { return FieldDescriptorProto_Label_Parse(name, value); } - + // accessors ------------------------------------------------------- - + // optional string name = 1; inline bool has_name() const; inline void clear_name(); @@ -818,28 +846,30 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa inline void set_name(const char* value); inline void set_name(const char* value, size_t size); inline ::std::string* mutable_name(); - + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + // optional int32 number = 3; inline bool has_number() const; inline void clear_number(); static const int kNumberFieldNumber = 3; inline ::google::protobuf::int32 number() const; inline void set_number(::google::protobuf::int32 value); - + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; inline bool has_label() const; inline void clear_label(); static const int kLabelFieldNumber = 4; inline ::google::protobuf::FieldDescriptorProto_Label label() const; inline void set_label(::google::protobuf::FieldDescriptorProto_Label value); - + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; inline bool has_type() const; inline void clear_type(); static const int kTypeFieldNumber = 5; inline ::google::protobuf::FieldDescriptorProto_Type type() const; inline void set_type(::google::protobuf::FieldDescriptorProto_Type value); - + // optional string type_name = 6; inline bool has_type_name() const; inline void clear_type_name(); @@ -849,7 +879,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa inline void set_type_name(const char* value); inline void set_type_name(const char* value, size_t size); inline ::std::string* mutable_type_name(); - + inline ::std::string* release_type_name(); + inline void set_allocated_type_name(::std::string* type_name); + // optional string extendee = 2; inline bool has_extendee() const; inline void clear_extendee(); @@ -859,7 +891,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa inline void set_extendee(const char* value); inline void set_extendee(const char* value, size_t size); inline ::std::string* mutable_extendee(); - + inline ::std::string* release_extendee(); + inline void set_allocated_extendee(::std::string* extendee); + // optional string default_value = 7; inline bool has_default_value() const; inline void clear_default_value(); @@ -869,50 +903,149 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa inline void set_default_value(const char* value); inline void set_default_value(const char* value, size_t size); inline ::std::string* mutable_default_value(); - + inline ::std::string* release_default_value(); + inline void set_allocated_default_value(::std::string* default_value); + + // optional int32 oneof_index = 9; + inline bool has_oneof_index() const; + inline void clear_oneof_index(); + static const int kOneofIndexFieldNumber = 9; + inline ::google::protobuf::int32 oneof_index() const; + inline void set_oneof_index(::google::protobuf::int32 value); + // optional .google.protobuf.FieldOptions options = 8; inline bool has_options() const; inline void clear_options(); static const int kOptionsFieldNumber = 8; inline const ::google::protobuf::FieldOptions& options() const; inline ::google::protobuf::FieldOptions* mutable_options(); - + inline ::google::protobuf::FieldOptions* release_options(); + inline void set_allocated_options(::google::protobuf::FieldOptions* options); + // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_number(); + inline void clear_has_number(); + inline void set_has_label(); + inline void clear_has_label(); + inline void set_has_type(); + inline void clear_has_type(); + inline void set_has_type_name(); + inline void clear_has_type_name(); + inline void set_has_extendee(); + inline void clear_has_extendee(); + inline void set_has_default_value(); + inline void clear_has_default_value(); + inline void set_has_oneof_index(); + inline void clear_has_oneof_index(); + inline void set_has_options(); + inline void clear_has_options(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::std::string* name_; - static const ::std::string _default_name_; ::google::protobuf::int32 number_; int label_; - int type_; ::std::string* type_name_; - static const ::std::string _default_type_name_; ::std::string* extendee_; - static const ::std::string _default_extendee_; + int type_; + ::google::protobuf::int32 oneof_index_; ::std::string* default_value_; - static const ::std::string _default_default_value_; ::google::protobuf::FieldOptions* options_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; + + void InitAsDefaultInstance(); + static FieldDescriptorProto* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT OneofDescriptorProto : public ::google::protobuf::Message { + public: + OneofDescriptorProto(); + virtual ~OneofDescriptorProto(); + + OneofDescriptorProto(const OneofDescriptorProto& from); + + inline OneofDescriptorProto& operator=(const OneofDescriptorProto& from) { + CopyFrom(from); + return *this; } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; } - + + static const ::google::protobuf::Descriptor* descriptor(); + static const OneofDescriptorProto& default_instance(); + + void Swap(OneofDescriptorProto* other); + + // implements Message ---------------------------------------------- + + OneofDescriptorProto* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const OneofDescriptorProto& from); + void MergeFrom(const OneofDescriptorProto& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional string name = 1; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 1; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + + // @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto) + private: + inline void set_has_name(); + inline void clear_has_name(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; + ::std::string* name_; + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + void InitAsDefaultInstance(); - static FieldDescriptorProto* default_instance_; + static OneofDescriptorProto* default_instance_; }; // ------------------------------------------------------------------- @@ -920,29 +1053,29 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag public: EnumDescriptorProto(); virtual ~EnumDescriptorProto(); - + EnumDescriptorProto(const EnumDescriptorProto& from); - + inline EnumDescriptorProto& operator=(const EnumDescriptorProto& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const EnumDescriptorProto& default_instance(); - + void Swap(EnumDescriptorProto* other); - + // implements Message ---------------------------------------------- - + EnumDescriptorProto* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -950,7 +1083,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag void MergeFrom(const EnumDescriptorProto& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -963,13 +1096,12 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // optional string name = 1; inline bool has_name() const; inline void clear_name(); @@ -979,7 +1111,9 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag inline void set_name(const char* value); inline void set_name(const char* value, size_t size); inline ::std::string* mutable_name(); - + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; inline int value_size() const; inline void clear_value(); @@ -991,40 +1125,34 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag value() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* mutable_value(); - + // optional .google.protobuf.EnumOptions options = 3; inline bool has_options() const; inline void clear_options(); static const int kOptionsFieldNumber = 3; inline const ::google::protobuf::EnumOptions& options() const; inline ::google::protobuf::EnumOptions* mutable_options(); - + inline ::google::protobuf::EnumOptions* release_options(); + inline void set_allocated_options(::google::protobuf::EnumOptions* options); + // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_options(); + inline void clear_has_options(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::std::string* name_; - static const ::std::string _default_name_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_; ::google::protobuf::EnumOptions* options_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static EnumDescriptorProto* default_instance_; }; @@ -1034,29 +1162,29 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M public: EnumValueDescriptorProto(); virtual ~EnumValueDescriptorProto(); - + EnumValueDescriptorProto(const EnumValueDescriptorProto& from); - + inline EnumValueDescriptorProto& operator=(const EnumValueDescriptorProto& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const EnumValueDescriptorProto& default_instance(); - + void Swap(EnumValueDescriptorProto* other); - + // implements Message ---------------------------------------------- - + EnumValueDescriptorProto* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -1064,7 +1192,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M void MergeFrom(const EnumValueDescriptorProto& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -1077,13 +1205,12 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // optional string name = 1; inline bool has_name() const; inline void clear_name(); @@ -1093,47 +1220,45 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M inline void set_name(const char* value); inline void set_name(const char* value, size_t size); inline ::std::string* mutable_name(); - + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + // optional int32 number = 2; inline bool has_number() const; inline void clear_number(); static const int kNumberFieldNumber = 2; inline ::google::protobuf::int32 number() const; inline void set_number(::google::protobuf::int32 value); - + // optional .google.protobuf.EnumValueOptions options = 3; inline bool has_options() const; inline void clear_options(); static const int kOptionsFieldNumber = 3; inline const ::google::protobuf::EnumValueOptions& options() const; inline ::google::protobuf::EnumValueOptions* mutable_options(); - + inline ::google::protobuf::EnumValueOptions* release_options(); + inline void set_allocated_options(::google::protobuf::EnumValueOptions* options); + // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_number(); + inline void clear_has_number(); + inline void set_has_options(); + inline void clear_has_options(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::std::string* name_; - static const ::std::string _default_name_; - ::google::protobuf::int32 number_; ::google::protobuf::EnumValueOptions* options_; + ::google::protobuf::int32 number_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static EnumValueDescriptorProto* default_instance_; }; @@ -1143,29 +1268,29 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes public: ServiceDescriptorProto(); virtual ~ServiceDescriptorProto(); - + ServiceDescriptorProto(const ServiceDescriptorProto& from); - + inline ServiceDescriptorProto& operator=(const ServiceDescriptorProto& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const ServiceDescriptorProto& default_instance(); - + void Swap(ServiceDescriptorProto* other); - + // implements Message ---------------------------------------------- - + ServiceDescriptorProto* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -1173,7 +1298,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes void MergeFrom(const ServiceDescriptorProto& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -1186,13 +1311,12 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // optional string name = 1; inline bool has_name() const; inline void clear_name(); @@ -1202,7 +1326,9 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes inline void set_name(const char* value); inline void set_name(const char* value, size_t size); inline ::std::string* mutable_name(); - + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + // repeated .google.protobuf.MethodDescriptorProto method = 2; inline int method_size() const; inline void clear_method(); @@ -1214,40 +1340,34 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes method() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* mutable_method(); - + // optional .google.protobuf.ServiceOptions options = 3; inline bool has_options() const; inline void clear_options(); static const int kOptionsFieldNumber = 3; inline const ::google::protobuf::ServiceOptions& options() const; inline ::google::protobuf::ServiceOptions* mutable_options(); - + inline ::google::protobuf::ServiceOptions* release_options(); + inline void set_allocated_options(::google::protobuf::ServiceOptions* options); + // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_options(); + inline void clear_has_options(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::std::string* name_; - static const ::std::string _default_name_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_; ::google::protobuf::ServiceOptions* options_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static ServiceDescriptorProto* default_instance_; }; @@ -1257,29 +1377,29 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess public: MethodDescriptorProto(); virtual ~MethodDescriptorProto(); - + MethodDescriptorProto(const MethodDescriptorProto& from); - + inline MethodDescriptorProto& operator=(const MethodDescriptorProto& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const MethodDescriptorProto& default_instance(); - + void Swap(MethodDescriptorProto* other); - + // implements Message ---------------------------------------------- - + MethodDescriptorProto* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -1287,7 +1407,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess void MergeFrom(const MethodDescriptorProto& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -1300,13 +1420,12 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // optional string name = 1; inline bool has_name() const; inline void clear_name(); @@ -1316,7 +1435,9 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess inline void set_name(const char* value); inline void set_name(const char* value, size_t size); inline ::std::string* mutable_name(); - + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + // optional string input_type = 2; inline bool has_input_type() const; inline void clear_input_type(); @@ -1326,7 +1447,9 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess inline void set_input_type(const char* value); inline void set_input_type(const char* value, size_t size); inline ::std::string* mutable_input_type(); - + inline ::std::string* release_input_type(); + inline void set_allocated_input_type(::std::string* input_type); + // optional string output_type = 3; inline bool has_output_type() const; inline void clear_output_type(); @@ -1336,43 +1459,41 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess inline void set_output_type(const char* value); inline void set_output_type(const char* value, size_t size); inline ::std::string* mutable_output_type(); - + inline ::std::string* release_output_type(); + inline void set_allocated_output_type(::std::string* output_type); + // optional .google.protobuf.MethodOptions options = 4; inline bool has_options() const; inline void clear_options(); static const int kOptionsFieldNumber = 4; inline const ::google::protobuf::MethodOptions& options() const; inline ::google::protobuf::MethodOptions* mutable_options(); - + inline ::google::protobuf::MethodOptions* release_options(); + inline void set_allocated_options(::google::protobuf::MethodOptions* options); + // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_input_type(); + inline void clear_has_input_type(); + inline void set_has_output_type(); + inline void clear_has_output_type(); + inline void set_has_options(); + inline void clear_has_options(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::std::string* name_; - static const ::std::string _default_name_; ::std::string* input_type_; - static const ::std::string _default_input_type_; ::std::string* output_type_; - static const ::std::string _default_output_type_; ::google::protobuf::MethodOptions* options_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static MethodDescriptorProto* default_instance_; }; @@ -1382,29 +1503,29 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { public: FileOptions(); virtual ~FileOptions(); - + FileOptions(const FileOptions& from); - + inline FileOptions& operator=(const FileOptions& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const FileOptions& default_instance(); - + void Swap(FileOptions* other); - + // implements Message ---------------------------------------------- - + FileOptions* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -1412,7 +1533,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { void MergeFrom(const FileOptions& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -1425,11 +1546,10 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + typedef FileOptions_OptimizeMode OptimizeMode; static const OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED; static const OptimizeMode CODE_SIZE = FileOptions_OptimizeMode_CODE_SIZE; @@ -1454,9 +1574,9 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { OptimizeMode* value) { return FileOptions_OptimizeMode_Parse(name, value); } - + // accessors ------------------------------------------------------- - + // optional string java_package = 1; inline bool has_java_package() const; inline void clear_java_package(); @@ -1466,7 +1586,9 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline void set_java_package(const char* value); inline void set_java_package(const char* value, size_t size); inline ::std::string* mutable_java_package(); - + inline ::std::string* release_java_package(); + inline void set_allocated_java_package(::std::string* java_package); + // optional string java_outer_classname = 8; inline bool has_java_outer_classname() const; inline void clear_java_outer_classname(); @@ -1476,42 +1598,77 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline void set_java_outer_classname(const char* value); inline void set_java_outer_classname(const char* value, size_t size); inline ::std::string* mutable_java_outer_classname(); - + inline ::std::string* release_java_outer_classname(); + inline void set_allocated_java_outer_classname(::std::string* java_outer_classname); + // optional bool java_multiple_files = 10 [default = false]; inline bool has_java_multiple_files() const; inline void clear_java_multiple_files(); static const int kJavaMultipleFilesFieldNumber = 10; inline bool java_multiple_files() const; inline void set_java_multiple_files(bool value); - + + // optional bool java_generate_equals_and_hash = 20 [default = false]; + inline bool has_java_generate_equals_and_hash() const; + inline void clear_java_generate_equals_and_hash(); + static const int kJavaGenerateEqualsAndHashFieldNumber = 20; + inline bool java_generate_equals_and_hash() const; + inline void set_java_generate_equals_and_hash(bool value); + + // optional bool java_string_check_utf8 = 27 [default = false]; + inline bool has_java_string_check_utf8() const; + inline void clear_java_string_check_utf8(); + static const int kJavaStringCheckUtf8FieldNumber = 27; + inline bool java_string_check_utf8() const; + inline void set_java_string_check_utf8(bool value); + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; inline bool has_optimize_for() const; inline void clear_optimize_for(); static const int kOptimizeForFieldNumber = 9; inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const; inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value); - - // optional bool cc_generic_services = 16 [default = true]; + + // optional string go_package = 11; + inline bool has_go_package() const; + inline void clear_go_package(); + static const int kGoPackageFieldNumber = 11; + inline const ::std::string& go_package() const; + inline void set_go_package(const ::std::string& value); + inline void set_go_package(const char* value); + inline void set_go_package(const char* value, size_t size); + inline ::std::string* mutable_go_package(); + inline ::std::string* release_go_package(); + inline void set_allocated_go_package(::std::string* go_package); + + // optional bool cc_generic_services = 16 [default = false]; inline bool has_cc_generic_services() const; inline void clear_cc_generic_services(); static const int kCcGenericServicesFieldNumber = 16; inline bool cc_generic_services() const; inline void set_cc_generic_services(bool value); - - // optional bool java_generic_services = 17 [default = true]; + + // optional bool java_generic_services = 17 [default = false]; inline bool has_java_generic_services() const; inline void clear_java_generic_services(); static const int kJavaGenericServicesFieldNumber = 17; inline bool java_generic_services() const; inline void set_java_generic_services(bool value); - - // optional bool py_generic_services = 18 [default = true]; + + // optional bool py_generic_services = 18 [default = false]; inline bool has_py_generic_services() const; inline void clear_py_generic_services(); static const int kPyGenericServicesFieldNumber = 18; inline bool py_generic_services() const; inline void set_py_generic_services(bool value); - + + // optional bool deprecated = 23 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 23; + inline bool deprecated() const; + inline void set_deprecated(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -1523,41 +1680,55 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { uninterpreted_option() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); - + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions) // @@protoc_insertion_point(class_scope:google.protobuf.FileOptions) private: + inline void set_has_java_package(); + inline void clear_has_java_package(); + inline void set_has_java_outer_classname(); + inline void clear_has_java_outer_classname(); + inline void set_has_java_multiple_files(); + inline void clear_has_java_multiple_files(); + inline void set_has_java_generate_equals_and_hash(); + inline void clear_has_java_generate_equals_and_hash(); + inline void set_has_java_string_check_utf8(); + inline void clear_has_java_string_check_utf8(); + inline void set_has_optimize_for(); + inline void clear_has_optimize_for(); + inline void set_has_go_package(); + inline void clear_has_go_package(); + inline void set_has_cc_generic_services(); + inline void clear_has_cc_generic_services(); + inline void set_has_java_generic_services(); + inline void clear_has_java_generic_services(); + inline void set_has_py_generic_services(); + inline void clear_has_py_generic_services(); + inline void set_has_deprecated(); + inline void clear_has_deprecated(); + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::std::string* java_package_; - static const ::std::string _default_java_package_; ::std::string* java_outer_classname_; - static const ::std::string _default_java_outer_classname_; bool java_multiple_files_; - int optimize_for_; + bool java_generate_equals_and_hash_; + bool java_string_check_utf8_; bool cc_generic_services_; + int optimize_for_; + ::std::string* go_package_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; bool java_generic_services_; bool py_generic_services_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool deprecated_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static FileOptions* default_instance_; }; @@ -1567,29 +1738,29 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { public: MessageOptions(); virtual ~MessageOptions(); - + MessageOptions(const MessageOptions& from); - + inline MessageOptions& operator=(const MessageOptions& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const MessageOptions& default_instance(); - + void Swap(MessageOptions* other); - + // implements Message ---------------------------------------------- - + MessageOptions* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -1597,7 +1768,7 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { void MergeFrom(const MessageOptions& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -1610,27 +1781,33 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // optional bool message_set_wire_format = 1 [default = false]; inline bool has_message_set_wire_format() const; inline void clear_message_set_wire_format(); static const int kMessageSetWireFormatFieldNumber = 1; inline bool message_set_wire_format() const; inline void set_message_set_wire_format(bool value); - + // optional bool no_standard_descriptor_accessor = 2 [default = false]; inline bool has_no_standard_descriptor_accessor() const; inline void clear_no_standard_descriptor_accessor(); static const int kNoStandardDescriptorAccessorFieldNumber = 2; inline bool no_standard_descriptor_accessor() const; inline void set_no_standard_descriptor_accessor(bool value); - + + // optional bool deprecated = 3 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 3; + inline bool deprecated() const; + inline void set_deprecated(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -1642,34 +1819,31 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { uninterpreted_option() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); - + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions) // @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions) private: + inline void set_has_message_set_wire_format(); + inline void clear_has_message_set_wire_format(); + inline void set_has_no_standard_descriptor_accessor(); + inline void clear_has_no_standard_descriptor_accessor(); + inline void set_has_deprecated(); + inline void clear_has_deprecated(); + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; bool message_set_wire_format_; bool no_standard_descriptor_accessor_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool deprecated_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static MessageOptions* default_instance_; }; @@ -1679,29 +1853,29 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { public: FieldOptions(); virtual ~FieldOptions(); - + FieldOptions(const FieldOptions& from); - + inline FieldOptions& operator=(const FieldOptions& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const FieldOptions& default_instance(); - + void Swap(FieldOptions* other); - + // implements Message ---------------------------------------------- - + FieldOptions* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -1709,7 +1883,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { void MergeFrom(const FieldOptions& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -1722,11 +1896,10 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + typedef FieldOptions_CType CType; static const CType STRING = FieldOptions_CType_STRING; static const CType CORD = FieldOptions_CType_CORD; @@ -1751,30 +1924,37 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { CType* value) { return FieldOptions_CType_Parse(name, value); } - + // accessors ------------------------------------------------------- - + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; inline bool has_ctype() const; inline void clear_ctype(); static const int kCtypeFieldNumber = 1; inline ::google::protobuf::FieldOptions_CType ctype() const; inline void set_ctype(::google::protobuf::FieldOptions_CType value); - + // optional bool packed = 2; inline bool has_packed() const; inline void clear_packed(); static const int kPackedFieldNumber = 2; inline bool packed() const; inline void set_packed(bool value); - + + // optional bool lazy = 5 [default = false]; + inline bool has_lazy() const; + inline void clear_lazy(); + static const int kLazyFieldNumber = 5; + inline bool lazy() const; + inline void set_lazy(bool value); + // optional bool deprecated = 3 [default = false]; inline bool has_deprecated() const; inline void clear_deprecated(); static const int kDeprecatedFieldNumber = 3; inline bool deprecated() const; inline void set_deprecated(bool value); - + // optional string experimental_map_key = 9; inline bool has_experimental_map_key() const; inline void clear_experimental_map_key(); @@ -1784,7 +1964,16 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { inline void set_experimental_map_key(const char* value); inline void set_experimental_map_key(const char* value, size_t size); inline ::std::string* mutable_experimental_map_key(); - + inline ::std::string* release_experimental_map_key(); + inline void set_allocated_experimental_map_key(::std::string* experimental_map_key); + + // optional bool weak = 10 [default = false]; + inline bool has_weak() const; + inline void clear_weak(); + static const int kWeakFieldNumber = 10; + inline bool weak() const; + inline void set_weak(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -1796,37 +1985,40 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { uninterpreted_option() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); - + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions) // @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions) private: + inline void set_has_ctype(); + inline void clear_has_ctype(); + inline void set_has_packed(); + inline void clear_has_packed(); + inline void set_has_lazy(); + inline void clear_has_lazy(); + inline void set_has_deprecated(); + inline void clear_has_deprecated(); + inline void set_has_experimental_map_key(); + inline void clear_has_experimental_map_key(); + inline void set_has_weak(); + inline void clear_has_weak(); + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - int ctype_; bool packed_; + bool lazy_; bool deprecated_; + bool weak_; ::std::string* experimental_map_key_; - static const ::std::string _default_experimental_map_key_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static FieldOptions* default_instance_; }; @@ -1836,29 +2028,29 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { public: EnumOptions(); virtual ~EnumOptions(); - + EnumOptions(const EnumOptions& from); - + inline EnumOptions& operator=(const EnumOptions& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const EnumOptions& default_instance(); - + void Swap(EnumOptions* other); - + // implements Message ---------------------------------------------- - + EnumOptions* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -1866,7 +2058,7 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { void MergeFrom(const EnumOptions& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -1879,13 +2071,26 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + + // optional bool allow_alias = 2; + inline bool has_allow_alias() const; + inline void clear_allow_alias(); + static const int kAllowAliasFieldNumber = 2; + inline bool allow_alias() const; + inline void set_allow_alias(bool value); + + // optional bool deprecated = 3 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 3; + inline bool deprecated() const; + inline void set_deprecated(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -1897,32 +2102,28 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { uninterpreted_option() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); - + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions) // @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions) private: + inline void set_has_allow_alias(); + inline void clear_has_allow_alias(); + inline void set_has_deprecated(); + inline void clear_has_deprecated(); + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool allow_alias_; + bool deprecated_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static EnumOptions* default_instance_; }; @@ -1932,29 +2133,29 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { public: EnumValueOptions(); virtual ~EnumValueOptions(); - + EnumValueOptions(const EnumValueOptions& from); - + inline EnumValueOptions& operator=(const EnumValueOptions& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const EnumValueOptions& default_instance(); - + void Swap(EnumValueOptions* other); - + // implements Message ---------------------------------------------- - + EnumValueOptions* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -1962,7 +2163,7 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { void MergeFrom(const EnumValueOptions& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -1975,13 +2176,19 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + + // optional bool deprecated = 1 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 1; + inline bool deprecated() const; + inline void set_deprecated(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -1993,32 +2200,25 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { uninterpreted_option() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); - + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions) // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions) private: + inline void set_has_deprecated(); + inline void clear_has_deprecated(); + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool deprecated_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static EnumValueOptions* default_instance_; }; @@ -2028,29 +2228,29 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { public: ServiceOptions(); virtual ~ServiceOptions(); - + ServiceOptions(const ServiceOptions& from); - + inline ServiceOptions& operator=(const ServiceOptions& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const ServiceOptions& default_instance(); - + void Swap(ServiceOptions* other); - + // implements Message ---------------------------------------------- - + ServiceOptions* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -2058,7 +2258,7 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { void MergeFrom(const ServiceOptions& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -2071,13 +2271,19 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + + // optional bool deprecated = 33 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 33; + inline bool deprecated() const; + inline void set_deprecated(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -2089,32 +2295,25 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { uninterpreted_option() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); - + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions) // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions) private: + inline void set_has_deprecated(); + inline void clear_has_deprecated(); + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool deprecated_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static ServiceOptions* default_instance_; }; @@ -2124,29 +2323,29 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { public: MethodOptions(); virtual ~MethodOptions(); - + MethodOptions(const MethodOptions& from); - + inline MethodOptions& operator=(const MethodOptions& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const MethodOptions& default_instance(); - + void Swap(MethodOptions* other); - + // implements Message ---------------------------------------------- - + MethodOptions* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -2154,7 +2353,7 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { void MergeFrom(const MethodOptions& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -2167,13 +2366,19 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + + // optional bool deprecated = 33 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 33; + inline bool deprecated() const; + inline void set_deprecated(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -2185,32 +2390,25 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { uninterpreted_option() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); - + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions) // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions) private: + inline void set_has_deprecated(); + inline void clear_has_deprecated(); + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool deprecated_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static MethodOptions* default_instance_; }; @@ -2220,29 +2418,29 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu public: UninterpretedOption_NamePart(); virtual ~UninterpretedOption_NamePart(); - + UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from); - + inline UninterpretedOption_NamePart& operator=(const UninterpretedOption_NamePart& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const UninterpretedOption_NamePart& default_instance(); - + void Swap(UninterpretedOption_NamePart* other); - + // implements Message ---------------------------------------------- - + UninterpretedOption_NamePart* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -2250,7 +2448,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu void MergeFrom(const UninterpretedOption_NamePart& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -2263,13 +2461,12 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + // accessors ------------------------------------------------------- - + // required string name_part = 1; inline bool has_name_part() const; inline void clear_name_part(); @@ -2279,39 +2476,33 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu inline void set_name_part(const char* value); inline void set_name_part(const char* value, size_t size); inline ::std::string* mutable_name_part(); - + inline ::std::string* release_name_part(); + inline void set_allocated_name_part(::std::string* name_part); + // required bool is_extension = 2; inline bool has_is_extension() const; inline void clear_is_extension(); static const int kIsExtensionFieldNumber = 2; inline bool is_extension() const; inline void set_is_extension(bool value); - + // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart) private: + inline void set_has_name_part(); + inline void clear_has_name_part(); + inline void set_has_is_extension(); + inline void clear_has_is_extension(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::std::string* name_part_; - static const ::std::string _default_name_part_; bool is_extension_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - + void InitAsDefaultInstance(); static UninterpretedOption_NamePart* default_instance_; }; @@ -2321,29 +2512,29 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag public: UninterpretedOption(); virtual ~UninterpretedOption(); - + UninterpretedOption(const UninterpretedOption& from); - + inline UninterpretedOption& operator=(const UninterpretedOption& from) { CopyFrom(from); return *this; } - + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { return _unknown_fields_; } - + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { return &_unknown_fields_; } - + static const ::google::protobuf::Descriptor* descriptor(); static const UninterpretedOption& default_instance(); - + void Swap(UninterpretedOption* other); - + // implements Message ---------------------------------------------- - + UninterpretedOption* New() const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); @@ -2351,7 +2542,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag void MergeFrom(const UninterpretedOption& from); void Clear(); bool IsInitialized() const; - + int ByteSize() const; bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input); @@ -2364,15 +2555,14 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; - + // nested types ---------------------------------------------------- - + typedef UninterpretedOption_NamePart NamePart; - + // accessors ------------------------------------------------------- - + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; inline int name_size() const; inline void clear_name(); @@ -2384,7 +2574,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag name() const; inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* mutable_name(); - + // optional string identifier_value = 3; inline bool has_identifier_value() const; inline void clear_identifier_value(); @@ -2394,28 +2584,30 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag inline void set_identifier_value(const char* value); inline void set_identifier_value(const char* value, size_t size); inline ::std::string* mutable_identifier_value(); - + inline ::std::string* release_identifier_value(); + inline void set_allocated_identifier_value(::std::string* identifier_value); + // optional uint64 positive_int_value = 4; inline bool has_positive_int_value() const; inline void clear_positive_int_value(); static const int kPositiveIntValueFieldNumber = 4; inline ::google::protobuf::uint64 positive_int_value() const; inline void set_positive_int_value(::google::protobuf::uint64 value); - + // optional int64 negative_int_value = 5; inline bool has_negative_int_value() const; inline void clear_negative_int_value(); static const int kNegativeIntValueFieldNumber = 5; inline ::google::protobuf::int64 negative_int_value() const; inline void set_negative_int_value(::google::protobuf::int64 value); - + // optional double double_value = 6; inline bool has_double_value() const; inline void clear_double_value(); static const int kDoubleValueFieldNumber = 6; inline double double_value() const; inline void set_double_value(double value); - + // optional bytes string_value = 7; inline bool has_string_value() const; inline void clear_string_value(); @@ -2425,39 +2617,264 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag inline void set_string_value(const char* value); inline void set_string_value(const void* value, size_t size); inline ::std::string* mutable_string_value(); - + inline ::std::string* release_string_value(); + inline void set_allocated_string_value(::std::string* string_value); + + // optional string aggregate_value = 8; + inline bool has_aggregate_value() const; + inline void clear_aggregate_value(); + static const int kAggregateValueFieldNumber = 8; + inline const ::std::string& aggregate_value() const; + inline void set_aggregate_value(const ::std::string& value); + inline void set_aggregate_value(const char* value); + inline void set_aggregate_value(const char* value, size_t size); + inline ::std::string* mutable_aggregate_value(); + inline ::std::string* release_aggregate_value(); + inline void set_allocated_aggregate_value(::std::string* aggregate_value); + // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption) private: + inline void set_has_identifier_value(); + inline void clear_has_identifier_value(); + inline void set_has_positive_int_value(); + inline void clear_has_positive_int_value(); + inline void set_has_negative_int_value(); + inline void clear_has_negative_int_value(); + inline void set_has_double_value(); + inline void clear_has_double_value(); + inline void set_has_string_value(); + inline void clear_has_string_value(); + inline void set_has_aggregate_value(); + inline void clear_has_aggregate_value(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart > name_; ::std::string* identifier_value_; - static const ::std::string _default_identifier_value_; ::google::protobuf::uint64 positive_int_value_; ::google::protobuf::int64 negative_int_value_; double double_value_; ::std::string* string_value_; - static const ::std::string _default_string_value_; + ::std::string* aggregate_value_; + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static UninterpretedOption* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Message { + public: + SourceCodeInfo_Location(); + virtual ~SourceCodeInfo_Location(); + + SourceCodeInfo_Location(const SourceCodeInfo_Location& from); + + inline SourceCodeInfo_Location& operator=(const SourceCodeInfo_Location& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const SourceCodeInfo_Location& default_instance(); + + void Swap(SourceCodeInfo_Location* other); + + // implements Message ---------------------------------------------- + + SourceCodeInfo_Location* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const SourceCodeInfo_Location& from); + void MergeFrom(const SourceCodeInfo_Location& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // repeated int32 path = 1 [packed = true]; + inline int path_size() const; + inline void clear_path(); + static const int kPathFieldNumber = 1; + inline ::google::protobuf::int32 path(int index) const; + inline void set_path(int index, ::google::protobuf::int32 value); + inline void add_path(::google::protobuf::int32 value); + inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + path() const; + inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + mutable_path(); + + // repeated int32 span = 2 [packed = true]; + inline int span_size() const; + inline void clear_span(); + static const int kSpanFieldNumber = 2; + inline ::google::protobuf::int32 span(int index) const; + inline void set_span(int index, ::google::protobuf::int32 value); + inline void add_span(::google::protobuf::int32 value); + inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + span() const; + inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + mutable_span(); + + // optional string leading_comments = 3; + inline bool has_leading_comments() const; + inline void clear_leading_comments(); + static const int kLeadingCommentsFieldNumber = 3; + inline const ::std::string& leading_comments() const; + inline void set_leading_comments(const ::std::string& value); + inline void set_leading_comments(const char* value); + inline void set_leading_comments(const char* value, size_t size); + inline ::std::string* mutable_leading_comments(); + inline ::std::string* release_leading_comments(); + inline void set_allocated_leading_comments(::std::string* leading_comments); + + // optional string trailing_comments = 4; + inline bool has_trailing_comments() const; + inline void clear_trailing_comments(); + static const int kTrailingCommentsFieldNumber = 4; + inline const ::std::string& trailing_comments() const; + inline void set_trailing_comments(const ::std::string& value); + inline void set_trailing_comments(const char* value); + inline void set_trailing_comments(const char* value, size_t size); + inline ::std::string* mutable_trailing_comments(); + inline ::std::string* release_trailing_comments(); + inline void set_allocated_trailing_comments(::std::string* trailing_comments); + + // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location) + private: + inline void set_has_leading_comments(); + inline void clear_has_leading_comments(); + inline void set_has_trailing_comments(); + inline void clear_has_trailing_comments(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; + ::google::protobuf::RepeatedField< ::google::protobuf::int32 > path_; + mutable int _path_cached_byte_size_; + ::google::protobuf::RepeatedField< ::google::protobuf::int32 > span_; + mutable int _span_cached_byte_size_; + ::std::string* leading_comments_; + ::std::string* trailing_comments_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - - ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; + + void InitAsDefaultInstance(); + static SourceCodeInfo_Location* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message { + public: + SourceCodeInfo(); + virtual ~SourceCodeInfo(); + + SourceCodeInfo(const SourceCodeInfo& from); + + inline SourceCodeInfo& operator=(const SourceCodeInfo& from) { + CopyFrom(from); + return *this; } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; } - + + static const ::google::protobuf::Descriptor* descriptor(); + static const SourceCodeInfo& default_instance(); + + void Swap(SourceCodeInfo* other); + + // implements Message ---------------------------------------------- + + SourceCodeInfo* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const SourceCodeInfo& from); + void MergeFrom(const SourceCodeInfo& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef SourceCodeInfo_Location Location; + + // accessors ------------------------------------------------------- + + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + inline int location_size() const; + inline void clear_location(); + static const int kLocationFieldNumber = 1; + inline const ::google::protobuf::SourceCodeInfo_Location& location(int index) const; + inline ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index); + inline ::google::protobuf::SourceCodeInfo_Location* add_location(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& + location() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* + mutable_location(); + + // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) + private: + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_; + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + void InitAsDefaultInstance(); - static UninterpretedOption* default_instance_; + static SourceCodeInfo* default_instance_; }; // =================================================================== @@ -2474,20 +2891,25 @@ inline void FileDescriptorSet::clear_file() { file_.Clear(); } inline const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file) return file_.Get(index); } inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file) return file_.Mutable(index); } inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file) return file_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& FileDescriptorSet::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file) return file_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* FileDescriptorSet::mutable_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file) return &file_; } @@ -2497,87 +2919,155 @@ FileDescriptorSet::mutable_file() { // optional string name = 1; inline bool FileDescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FileDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void FileDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void FileDescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& FileDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name) return *name_; } inline void FileDescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name) } inline void FileDescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name) } inline void FileDescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name) } inline ::std::string* FileDescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name) return name_; } +inline ::std::string* FileDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void FileDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name) +} // optional string package = 2; inline bool FileDescriptorProto::has_package() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FileDescriptorProto::set_has_package() { + _has_bits_[0] |= 0x00000002u; +} +inline void FileDescriptorProto::clear_has_package() { + _has_bits_[0] &= ~0x00000002u; } inline void FileDescriptorProto::clear_package() { - if (package_ != &_default_package_) { + if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { package_->clear(); } - _clear_bit(1); + clear_has_package(); } inline const ::std::string& FileDescriptorProto::package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package) return *package_; } inline void FileDescriptorProto::set_package(const ::std::string& value) { - _set_bit(1); - if (package_ == &_default_package_) { + set_has_package(); + if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { package_ = new ::std::string; } package_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package) } inline void FileDescriptorProto::set_package(const char* value) { - _set_bit(1); - if (package_ == &_default_package_) { + set_has_package(); + if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { package_ = new ::std::string; } package_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package) } inline void FileDescriptorProto::set_package(const char* value, size_t size) { - _set_bit(1); - if (package_ == &_default_package_) { + set_has_package(); + if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { package_ = new ::std::string; } package_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package) } inline ::std::string* FileDescriptorProto::mutable_package() { - _set_bit(1); - if (package_ == &_default_package_) { + set_has_package(); + if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { package_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package) return package_; } +inline ::std::string* FileDescriptorProto::release_package() { + clear_has_package(); + if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = package_; + package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void FileDescriptorProto::set_allocated_package(::std::string* package) { + if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete package_; + } + if (package) { + set_has_package(); + package_ = package; + } else { + clear_has_package(); + package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package) +} // repeated string dependency = 3; inline int FileDescriptorProto::dependency_size() const { @@ -2587,42 +3077,112 @@ inline void FileDescriptorProto::clear_dependency() { dependency_.Clear(); } inline const ::std::string& FileDescriptorProto::dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency) return dependency_.Get(index); } inline ::std::string* FileDescriptorProto::mutable_dependency(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency) return dependency_.Mutable(index); } inline void FileDescriptorProto::set_dependency(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency) dependency_.Mutable(index)->assign(value); } inline void FileDescriptorProto::set_dependency(int index, const char* value) { dependency_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency) } inline void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) { dependency_.Mutable(index)->assign( reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency) } inline ::std::string* FileDescriptorProto::add_dependency() { return dependency_.Add(); } inline void FileDescriptorProto::add_dependency(const ::std::string& value) { dependency_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency) } inline void FileDescriptorProto::add_dependency(const char* value) { dependency_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency) } inline void FileDescriptorProto::add_dependency(const char* value, size_t size) { dependency_.Add()->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency) } inline const ::google::protobuf::RepeatedPtrField< ::std::string>& FileDescriptorProto::dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency) return dependency_; } inline ::google::protobuf::RepeatedPtrField< ::std::string>* FileDescriptorProto::mutable_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.dependency) return &dependency_; } +// repeated int32 public_dependency = 10; +inline int FileDescriptorProto::public_dependency_size() const { + return public_dependency_.size(); +} +inline void FileDescriptorProto::clear_public_dependency() { + public_dependency_.Clear(); +} +inline ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency) + return public_dependency_.Get(index); +} +inline void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) { + public_dependency_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency) +} +inline void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) { + public_dependency_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency) +} +inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +FileDescriptorProto::public_dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency) + return public_dependency_; +} +inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +FileDescriptorProto::mutable_public_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency) + return &public_dependency_; +} + +// repeated int32 weak_dependency = 11; +inline int FileDescriptorProto::weak_dependency_size() const { + return weak_dependency_.size(); +} +inline void FileDescriptorProto::clear_weak_dependency() { + weak_dependency_.Clear(); +} +inline ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency) + return weak_dependency_.Get(index); +} +inline void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) { + weak_dependency_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency) +} +inline void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) { + weak_dependency_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency) +} +inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +FileDescriptorProto::weak_dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency) + return weak_dependency_; +} +inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +FileDescriptorProto::mutable_weak_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency) + return &weak_dependency_; +} + // repeated .google.protobuf.DescriptorProto message_type = 4; inline int FileDescriptorProto::message_type_size() const { return message_type_.size(); @@ -2631,20 +3191,25 @@ inline void FileDescriptorProto::clear_message_type() { message_type_.Clear(); } inline const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type) return message_type_.Get(index); } inline ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type) return message_type_.Mutable(index); } inline ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type) return message_type_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& FileDescriptorProto::message_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type) return message_type_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* FileDescriptorProto::mutable_message_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type) return &message_type_; } @@ -2656,20 +3221,25 @@ inline void FileDescriptorProto::clear_enum_type() { enum_type_.Clear(); } inline const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type) return enum_type_.Get(index); } inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type) return enum_type_.Mutable(index); } inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type) return enum_type_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& FileDescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type) return enum_type_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* FileDescriptorProto::mutable_enum_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type) return &enum_type_; } @@ -2681,20 +3251,25 @@ inline void FileDescriptorProto::clear_service() { service_.Clear(); } inline const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service) return service_.Get(index); } inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service) return service_.Mutable(index); } inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service) return service_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& FileDescriptorProto::service() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service) return service_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* FileDescriptorProto::mutable_service() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service) return &service_; } @@ -2706,39 +3281,109 @@ inline void FileDescriptorProto::clear_extension() { extension_.Clear(); } inline const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension) return extension_.Get(index); } inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension) return extension_.Mutable(index); } inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension) return extension_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& FileDescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension) return extension_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* FileDescriptorProto::mutable_extension() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension) return &extension_; } // optional .google.protobuf.FileOptions options = 8; inline bool FileDescriptorProto::has_options() const { - return _has_bit(7); + return (_has_bits_[0] & 0x00000200u) != 0; +} +inline void FileDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000200u; +} +inline void FileDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000200u; } inline void FileDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); - _clear_bit(7); + clear_has_options(); } inline const ::google::protobuf::FileOptions& FileDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() { - _set_bit(7); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::FileOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options) return options_; } +inline ::google::protobuf::FileOptions* FileDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::FileOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options) +} + +// optional .google.protobuf.SourceCodeInfo source_code_info = 9; +inline bool FileDescriptorProto::has_source_code_info() const { + return (_has_bits_[0] & 0x00000400u) != 0; +} +inline void FileDescriptorProto::set_has_source_code_info() { + _has_bits_[0] |= 0x00000400u; +} +inline void FileDescriptorProto::clear_has_source_code_info() { + _has_bits_[0] &= ~0x00000400u; +} +inline void FileDescriptorProto::clear_source_code_info() { + if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear(); + clear_has_source_code_info(); +} +inline const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info) + return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_; +} +inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() { + set_has_source_code_info(); + if (source_code_info_ == NULL) source_code_info_ = new ::google::protobuf::SourceCodeInfo; + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info) + return source_code_info_; +} +inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() { + clear_has_source_code_info(); + ::google::protobuf::SourceCodeInfo* temp = source_code_info_; + source_code_info_ = NULL; + return temp; +} +inline void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) { + delete source_code_info_; + source_code_info_ = source_code_info; + if (source_code_info) { + set_has_source_code_info(); + } else { + clear_has_source_code_info(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info) +} // ------------------------------------------------------------------- @@ -2746,34 +3391,50 @@ inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() { // optional int32 start = 1; inline bool DescriptorProto_ExtensionRange::has_start() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void DescriptorProto_ExtensionRange::set_has_start() { + _has_bits_[0] |= 0x00000001u; +} +inline void DescriptorProto_ExtensionRange::clear_has_start() { + _has_bits_[0] &= ~0x00000001u; } inline void DescriptorProto_ExtensionRange::clear_start() { start_ = 0; - _clear_bit(0); + clear_has_start(); } inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start) return start_; } inline void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) { - _set_bit(0); + set_has_start(); start_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start) } // optional int32 end = 2; inline bool DescriptorProto_ExtensionRange::has_end() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void DescriptorProto_ExtensionRange::set_has_end() { + _has_bits_[0] |= 0x00000002u; +} +inline void DescriptorProto_ExtensionRange::clear_has_end() { + _has_bits_[0] &= ~0x00000002u; } inline void DescriptorProto_ExtensionRange::clear_end() { end_ = 0; - _clear_bit(1); + clear_has_end(); } inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end) return end_; } inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) { - _set_bit(1); + set_has_end(); end_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end) } // ------------------------------------------------------------------- @@ -2782,45 +3443,79 @@ inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 va // optional string name = 1; inline bool DescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void DescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void DescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void DescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& DescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name) return *name_; } inline void DescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name) } inline void DescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name) } inline void DescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name) } inline ::std::string* DescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name) return name_; } +inline ::std::string* DescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void DescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name) +} // repeated .google.protobuf.FieldDescriptorProto field = 2; inline int DescriptorProto::field_size() const { @@ -2830,20 +3525,25 @@ inline void DescriptorProto::clear_field() { field_.Clear(); } inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field) return field_.Get(index); } inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field) return field_.Mutable(index); } inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field) return field_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& DescriptorProto::field() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field) return field_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* DescriptorProto::mutable_field() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field) return &field_; } @@ -2855,20 +3555,25 @@ inline void DescriptorProto::clear_extension() { extension_.Clear(); } inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension) return extension_.Get(index); } inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension) return extension_.Mutable(index); } inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension) return extension_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& DescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension) return extension_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* DescriptorProto::mutable_extension() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension) return &extension_; } @@ -2880,20 +3585,25 @@ inline void DescriptorProto::clear_nested_type() { nested_type_.Clear(); } inline const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type) return nested_type_.Get(index); } inline ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type) return nested_type_.Mutable(index); } inline ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type) return nested_type_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& DescriptorProto::nested_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type) return nested_type_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* DescriptorProto::mutable_nested_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type) return &nested_type_; } @@ -2905,20 +3615,25 @@ inline void DescriptorProto::clear_enum_type() { enum_type_.Clear(); } inline const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type) return enum_type_.Get(index); } inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type) return enum_type_.Mutable(index); } inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type) return enum_type_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& DescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type) return enum_type_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* DescriptorProto::mutable_enum_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type) return &enum_type_; } @@ -2930,39 +3645,98 @@ inline void DescriptorProto::clear_extension_range() { extension_range_.Clear(); } inline const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range) return extension_range_.Get(index); } inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range) return extension_range_.Mutable(index); } inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range) return extension_range_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& DescriptorProto::extension_range() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range) return extension_range_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* DescriptorProto::mutable_extension_range() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range) return &extension_range_; } +// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; +inline int DescriptorProto::oneof_decl_size() const { + return oneof_decl_.size(); +} +inline void DescriptorProto::clear_oneof_decl() { + oneof_decl_.Clear(); +} +inline const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_.Get(index); +} +inline ::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_.Mutable(index); +} +inline ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& +DescriptorProto::oneof_decl() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* +DescriptorProto::mutable_oneof_decl() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl) + return &oneof_decl_; +} + // optional .google.protobuf.MessageOptions options = 7; inline bool DescriptorProto::has_options() const { - return _has_bit(6); + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void DescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000080u; +} +inline void DescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000080u; } inline void DescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); - _clear_bit(6); + clear_has_options(); } inline const ::google::protobuf::MessageOptions& DescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() { - _set_bit(6); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::MessageOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options) return options_; } +inline ::google::protobuf::MessageOptions* DescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::MessageOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options) +} // ------------------------------------------------------------------- @@ -2970,326 +3744,677 @@ inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() { // optional string name = 1; inline bool FieldDescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FieldDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void FieldDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void FieldDescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& FieldDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name) return *name_; } inline void FieldDescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name) } inline void FieldDescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name) } inline void FieldDescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name) } inline ::std::string* FieldDescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name) return name_; } +inline ::std::string* FieldDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void FieldDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name) +} // optional int32 number = 3; inline bool FieldDescriptorProto::has_number() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FieldDescriptorProto::set_has_number() { + _has_bits_[0] |= 0x00000002u; +} +inline void FieldDescriptorProto::clear_has_number() { + _has_bits_[0] &= ~0x00000002u; } inline void FieldDescriptorProto::clear_number() { number_ = 0; - _clear_bit(1); + clear_has_number(); } inline ::google::protobuf::int32 FieldDescriptorProto::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number) return number_; } inline void FieldDescriptorProto::set_number(::google::protobuf::int32 value) { - _set_bit(1); + set_has_number(); number_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number) } // optional .google.protobuf.FieldDescriptorProto.Label label = 4; inline bool FieldDescriptorProto::has_label() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void FieldDescriptorProto::set_has_label() { + _has_bits_[0] |= 0x00000004u; +} +inline void FieldDescriptorProto::clear_has_label() { + _has_bits_[0] &= ~0x00000004u; } inline void FieldDescriptorProto::clear_label() { label_ = 1; - _clear_bit(2); + clear_has_label(); } inline ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.label) return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_); } inline void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) { - GOOGLE_DCHECK(::google::protobuf::FieldDescriptorProto_Label_IsValid(value)); - _set_bit(2); + assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value)); + set_has_label(); label_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.label) } // optional .google.protobuf.FieldDescriptorProto.Type type = 5; inline bool FieldDescriptorProto::has_type() const { - return _has_bit(3); + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void FieldDescriptorProto::set_has_type() { + _has_bits_[0] |= 0x00000008u; +} +inline void FieldDescriptorProto::clear_has_type() { + _has_bits_[0] &= ~0x00000008u; } inline void FieldDescriptorProto::clear_type() { type_ = 1; - _clear_bit(3); + clear_has_type(); } inline ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type) return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_); } inline void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) { - GOOGLE_DCHECK(::google::protobuf::FieldDescriptorProto_Type_IsValid(value)); - _set_bit(3); + assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value)); + set_has_type(); type_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type) } // optional string type_name = 6; inline bool FieldDescriptorProto::has_type_name() const { - return _has_bit(4); + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void FieldDescriptorProto::set_has_type_name() { + _has_bits_[0] |= 0x00000010u; +} +inline void FieldDescriptorProto::clear_has_type_name() { + _has_bits_[0] &= ~0x00000010u; } inline void FieldDescriptorProto::clear_type_name() { - if (type_name_ != &_default_type_name_) { + if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { type_name_->clear(); } - _clear_bit(4); + clear_has_type_name(); } inline const ::std::string& FieldDescriptorProto::type_name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name) return *type_name_; } inline void FieldDescriptorProto::set_type_name(const ::std::string& value) { - _set_bit(4); - if (type_name_ == &_default_type_name_) { + set_has_type_name(); + if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { type_name_ = new ::std::string; } type_name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name) } inline void FieldDescriptorProto::set_type_name(const char* value) { - _set_bit(4); - if (type_name_ == &_default_type_name_) { + set_has_type_name(); + if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { type_name_ = new ::std::string; } type_name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name) } inline void FieldDescriptorProto::set_type_name(const char* value, size_t size) { - _set_bit(4); - if (type_name_ == &_default_type_name_) { + set_has_type_name(); + if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { type_name_ = new ::std::string; } type_name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name) } inline ::std::string* FieldDescriptorProto::mutable_type_name() { - _set_bit(4); - if (type_name_ == &_default_type_name_) { + set_has_type_name(); + if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { type_name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name) return type_name_; } +inline ::std::string* FieldDescriptorProto::release_type_name() { + clear_has_type_name(); + if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = type_name_; + type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) { + if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete type_name_; + } + if (type_name) { + set_has_type_name(); + type_name_ = type_name; + } else { + clear_has_type_name(); + type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name) +} // optional string extendee = 2; inline bool FieldDescriptorProto::has_extendee() const { - return _has_bit(5); + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void FieldDescriptorProto::set_has_extendee() { + _has_bits_[0] |= 0x00000020u; +} +inline void FieldDescriptorProto::clear_has_extendee() { + _has_bits_[0] &= ~0x00000020u; } inline void FieldDescriptorProto::clear_extendee() { - if (extendee_ != &_default_extendee_) { + if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { extendee_->clear(); } - _clear_bit(5); + clear_has_extendee(); } inline const ::std::string& FieldDescriptorProto::extendee() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee) return *extendee_; } inline void FieldDescriptorProto::set_extendee(const ::std::string& value) { - _set_bit(5); - if (extendee_ == &_default_extendee_) { + set_has_extendee(); + if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { extendee_ = new ::std::string; } extendee_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee) } inline void FieldDescriptorProto::set_extendee(const char* value) { - _set_bit(5); - if (extendee_ == &_default_extendee_) { + set_has_extendee(); + if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { extendee_ = new ::std::string; } extendee_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee) } inline void FieldDescriptorProto::set_extendee(const char* value, size_t size) { - _set_bit(5); - if (extendee_ == &_default_extendee_) { + set_has_extendee(); + if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { extendee_ = new ::std::string; } extendee_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee) } inline ::std::string* FieldDescriptorProto::mutable_extendee() { - _set_bit(5); - if (extendee_ == &_default_extendee_) { + set_has_extendee(); + if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { extendee_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee) return extendee_; } +inline ::std::string* FieldDescriptorProto::release_extendee() { + clear_has_extendee(); + if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = extendee_; + extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) { + if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete extendee_; + } + if (extendee) { + set_has_extendee(); + extendee_ = extendee; + } else { + clear_has_extendee(); + extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee) +} // optional string default_value = 7; inline bool FieldDescriptorProto::has_default_value() const { - return _has_bit(6); + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void FieldDescriptorProto::set_has_default_value() { + _has_bits_[0] |= 0x00000040u; +} +inline void FieldDescriptorProto::clear_has_default_value() { + _has_bits_[0] &= ~0x00000040u; } inline void FieldDescriptorProto::clear_default_value() { - if (default_value_ != &_default_default_value_) { + if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { default_value_->clear(); } - _clear_bit(6); + clear_has_default_value(); } inline const ::std::string& FieldDescriptorProto::default_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value) return *default_value_; } inline void FieldDescriptorProto::set_default_value(const ::std::string& value) { - _set_bit(6); - if (default_value_ == &_default_default_value_) { + set_has_default_value(); + if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { default_value_ = new ::std::string; } default_value_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value) } inline void FieldDescriptorProto::set_default_value(const char* value) { - _set_bit(6); - if (default_value_ == &_default_default_value_) { + set_has_default_value(); + if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { default_value_ = new ::std::string; } default_value_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value) } inline void FieldDescriptorProto::set_default_value(const char* value, size_t size) { - _set_bit(6); - if (default_value_ == &_default_default_value_) { + set_has_default_value(); + if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { default_value_ = new ::std::string; } default_value_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value) } inline ::std::string* FieldDescriptorProto::mutable_default_value() { - _set_bit(6); - if (default_value_ == &_default_default_value_) { + set_has_default_value(); + if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { default_value_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value) return default_value_; } +inline ::std::string* FieldDescriptorProto::release_default_value() { + clear_has_default_value(); + if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = default_value_; + default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) { + if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete default_value_; + } + if (default_value) { + set_has_default_value(); + default_value_ = default_value; + } else { + clear_has_default_value(); + default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value) +} + +// optional int32 oneof_index = 9; +inline bool FieldDescriptorProto::has_oneof_index() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void FieldDescriptorProto::set_has_oneof_index() { + _has_bits_[0] |= 0x00000080u; +} +inline void FieldDescriptorProto::clear_has_oneof_index() { + _has_bits_[0] &= ~0x00000080u; +} +inline void FieldDescriptorProto::clear_oneof_index() { + oneof_index_ = 0; + clear_has_oneof_index(); +} +inline ::google::protobuf::int32 FieldDescriptorProto::oneof_index() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index) + return oneof_index_; +} +inline void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 value) { + set_has_oneof_index(); + oneof_index_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index) +} // optional .google.protobuf.FieldOptions options = 8; inline bool FieldDescriptorProto::has_options() const { - return _has_bit(7); + return (_has_bits_[0] & 0x00000100u) != 0; +} +inline void FieldDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000100u; +} +inline void FieldDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000100u; } inline void FieldDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); - _clear_bit(7); + clear_has_options(); } inline const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() { - _set_bit(7); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::FieldOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options) return options_; } +inline ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::FieldOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options) +} // ------------------------------------------------------------------- -// EnumDescriptorProto +// OneofDescriptorProto // optional string name = 1; -inline bool EnumDescriptorProto::has_name() const { - return _has_bit(0); +inline bool OneofDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; } -inline void EnumDescriptorProto::clear_name() { - if (name_ != &_default_name_) { +inline void OneofDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void OneofDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void OneofDescriptorProto::clear_name() { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } -inline const ::std::string& EnumDescriptorProto::name() const { +inline const ::std::string& OneofDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name) return *name_; } -inline void EnumDescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { +inline void OneofDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name) } -inline void EnumDescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { +inline void OneofDescriptorProto::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name) } -inline void EnumDescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { +inline void OneofDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name) } -inline ::std::string* EnumDescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { +inline ::std::string* OneofDescriptorProto::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name) return name_; } - -// repeated .google.protobuf.EnumValueDescriptorProto value = 2; -inline int EnumDescriptorProto::value_size() const { - return value_.size(); +inline ::std::string* OneofDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } } -inline void EnumDescriptorProto::clear_value() { - value_.Clear(); +inline void OneofDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name) +} + +// ------------------------------------------------------------------- + +// EnumDescriptorProto + +// optional string name = 1; +inline bool EnumDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void EnumDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void EnumDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void EnumDescriptorProto::clear_name() { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& EnumDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name) + return *name_; +} +inline void EnumDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + name_ = new ::std::string; + } + name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name) +} +inline void EnumDescriptorProto::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + name_ = new ::std::string; + } + name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name) +} +inline void EnumDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name) +} +inline ::std::string* EnumDescriptorProto::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + name_ = new ::std::string; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name) + return name_; +} +inline ::std::string* EnumDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void EnumDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name) +} + +// repeated .google.protobuf.EnumValueDescriptorProto value = 2; +inline int EnumDescriptorProto::value_size() const { + return value_.size(); +} +inline void EnumDescriptorProto::clear_value() { + value_.Clear(); } inline const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value) return value_.Get(index); } inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value) return value_.Mutable(index); } inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value) return value_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& EnumDescriptorProto::value() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value) return value_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* EnumDescriptorProto::mutable_value() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value) return &value_; } // optional .google.protobuf.EnumOptions options = 3; inline bool EnumDescriptorProto::has_options() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void EnumDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} +inline void EnumDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; } inline void EnumDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear(); - _clear_bit(2); + clear_has_options(); } inline const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() { - _set_bit(2); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::EnumOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options) return options_; } +inline ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::EnumOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options) +} // ------------------------------------------------------------------- @@ -3297,78 +4422,144 @@ inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() { // optional string name = 1; inline bool EnumValueDescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void EnumValueDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void EnumValueDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void EnumValueDescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& EnumValueDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name) return *name_; } inline void EnumValueDescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name) } inline void EnumValueDescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name) } inline void EnumValueDescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name) } inline ::std::string* EnumValueDescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name) return name_; } +inline ::std::string* EnumValueDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void EnumValueDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name) +} // optional int32 number = 2; inline bool EnumValueDescriptorProto::has_number() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void EnumValueDescriptorProto::set_has_number() { + _has_bits_[0] |= 0x00000002u; +} +inline void EnumValueDescriptorProto::clear_has_number() { + _has_bits_[0] &= ~0x00000002u; } inline void EnumValueDescriptorProto::clear_number() { number_ = 0; - _clear_bit(1); + clear_has_number(); } inline ::google::protobuf::int32 EnumValueDescriptorProto::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number) return number_; } inline void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) { - _set_bit(1); + set_has_number(); number_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number) } // optional .google.protobuf.EnumValueOptions options = 3; inline bool EnumValueDescriptorProto::has_options() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void EnumValueDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} +inline void EnumValueDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; } inline void EnumValueDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear(); - _clear_bit(2); + clear_has_options(); } inline const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() { - _set_bit(2); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::EnumValueOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options) return options_; } +inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::EnumValueOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options) +} // ------------------------------------------------------------------- @@ -3376,45 +4567,79 @@ inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_o // optional string name = 1; inline bool ServiceDescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ServiceDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void ServiceDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void ServiceDescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& ServiceDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name) return *name_; } inline void ServiceDescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name) } inline void ServiceDescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name) } inline void ServiceDescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name) } inline ::std::string* ServiceDescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name) return name_; } +inline ::std::string* ServiceDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void ServiceDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name) +} // repeated .google.protobuf.MethodDescriptorProto method = 2; inline int ServiceDescriptorProto::method_size() const { @@ -3424,39 +4649,68 @@ inline void ServiceDescriptorProto::clear_method() { method_.Clear(); } inline const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method) return method_.Get(index); } inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method) return method_.Mutable(index); } inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() { + // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method) return method_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& ServiceDescriptorProto::method() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method) return method_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* ServiceDescriptorProto::mutable_method() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method) return &method_; } // optional .google.protobuf.ServiceOptions options = 3; inline bool ServiceDescriptorProto::has_options() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void ServiceDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} +inline void ServiceDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; } inline void ServiceDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear(); - _clear_bit(2); + clear_has_options(); } inline const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() { - _set_bit(2); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::ServiceOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options) return options_; } +inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::ServiceOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options) +} // ------------------------------------------------------------------- @@ -3464,146 +4718,272 @@ inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_optio // optional string name = 1; inline bool MethodDescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void MethodDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void MethodDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void MethodDescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& MethodDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name) return *name_; } inline void MethodDescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name) } inline void MethodDescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name) } inline void MethodDescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name) } inline ::std::string* MethodDescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name) return name_; } +inline ::std::string* MethodDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void MethodDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name) +} // optional string input_type = 2; inline bool MethodDescriptorProto::has_input_type() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void MethodDescriptorProto::set_has_input_type() { + _has_bits_[0] |= 0x00000002u; +} +inline void MethodDescriptorProto::clear_has_input_type() { + _has_bits_[0] &= ~0x00000002u; } inline void MethodDescriptorProto::clear_input_type() { - if (input_type_ != &_default_input_type_) { + if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { input_type_->clear(); } - _clear_bit(1); + clear_has_input_type(); } inline const ::std::string& MethodDescriptorProto::input_type() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type) return *input_type_; } inline void MethodDescriptorProto::set_input_type(const ::std::string& value) { - _set_bit(1); - if (input_type_ == &_default_input_type_) { + set_has_input_type(); + if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { input_type_ = new ::std::string; } input_type_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type) } inline void MethodDescriptorProto::set_input_type(const char* value) { - _set_bit(1); - if (input_type_ == &_default_input_type_) { + set_has_input_type(); + if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { input_type_ = new ::std::string; } input_type_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type) } inline void MethodDescriptorProto::set_input_type(const char* value, size_t size) { - _set_bit(1); - if (input_type_ == &_default_input_type_) { + set_has_input_type(); + if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { input_type_ = new ::std::string; } input_type_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type) } inline ::std::string* MethodDescriptorProto::mutable_input_type() { - _set_bit(1); - if (input_type_ == &_default_input_type_) { + set_has_input_type(); + if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { input_type_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type) return input_type_; } +inline ::std::string* MethodDescriptorProto::release_input_type() { + clear_has_input_type(); + if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = input_type_; + input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) { + if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete input_type_; + } + if (input_type) { + set_has_input_type(); + input_type_ = input_type; + } else { + clear_has_input_type(); + input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type) +} // optional string output_type = 3; inline bool MethodDescriptorProto::has_output_type() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void MethodDescriptorProto::set_has_output_type() { + _has_bits_[0] |= 0x00000004u; +} +inline void MethodDescriptorProto::clear_has_output_type() { + _has_bits_[0] &= ~0x00000004u; } inline void MethodDescriptorProto::clear_output_type() { - if (output_type_ != &_default_output_type_) { + if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { output_type_->clear(); } - _clear_bit(2); + clear_has_output_type(); } inline const ::std::string& MethodDescriptorProto::output_type() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type) return *output_type_; } inline void MethodDescriptorProto::set_output_type(const ::std::string& value) { - _set_bit(2); - if (output_type_ == &_default_output_type_) { + set_has_output_type(); + if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { output_type_ = new ::std::string; } output_type_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type) } inline void MethodDescriptorProto::set_output_type(const char* value) { - _set_bit(2); - if (output_type_ == &_default_output_type_) { + set_has_output_type(); + if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { output_type_ = new ::std::string; } output_type_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type) } inline void MethodDescriptorProto::set_output_type(const char* value, size_t size) { - _set_bit(2); - if (output_type_ == &_default_output_type_) { + set_has_output_type(); + if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { output_type_ = new ::std::string; } output_type_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type) } inline ::std::string* MethodDescriptorProto::mutable_output_type() { - _set_bit(2); - if (output_type_ == &_default_output_type_) { + set_has_output_type(); + if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { output_type_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type) return output_type_; } +inline ::std::string* MethodDescriptorProto::release_output_type() { + clear_has_output_type(); + if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = output_type_; + output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) { + if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete output_type_; + } + if (output_type) { + set_has_output_type(); + output_type_ = output_type; + } else { + clear_has_output_type(); + output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type) +} // optional .google.protobuf.MethodOptions options = 4; inline bool MethodDescriptorProto::has_options() const { - return _has_bit(3); + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void MethodDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000008u; +} +inline void MethodDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000008u; } inline void MethodDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear(); - _clear_bit(3); + clear_has_options(); } inline const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() { - _set_bit(3); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::MethodOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options) return options_; } +inline ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::MethodOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options) +} // ------------------------------------------------------------------- @@ -3611,167 +4991,423 @@ inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options // optional string java_package = 1; inline bool FileOptions::has_java_package() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FileOptions::set_has_java_package() { + _has_bits_[0] |= 0x00000001u; +} +inline void FileOptions::clear_has_java_package() { + _has_bits_[0] &= ~0x00000001u; } inline void FileOptions::clear_java_package() { - if (java_package_ != &_default_java_package_) { + if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_package_->clear(); } - _clear_bit(0); + clear_has_java_package(); } inline const ::std::string& FileOptions::java_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package) return *java_package_; } inline void FileOptions::set_java_package(const ::std::string& value) { - _set_bit(0); - if (java_package_ == &_default_java_package_) { + set_has_java_package(); + if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_package_ = new ::std::string; } java_package_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package) } inline void FileOptions::set_java_package(const char* value) { - _set_bit(0); - if (java_package_ == &_default_java_package_) { + set_has_java_package(); + if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_package_ = new ::std::string; } java_package_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package) } inline void FileOptions::set_java_package(const char* value, size_t size) { - _set_bit(0); - if (java_package_ == &_default_java_package_) { + set_has_java_package(); + if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_package_ = new ::std::string; } java_package_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package) } inline ::std::string* FileOptions::mutable_java_package() { - _set_bit(0); - if (java_package_ == &_default_java_package_) { + set_has_java_package(); + if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_package_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package) return java_package_; } +inline ::std::string* FileOptions::release_java_package() { + clear_has_java_package(); + if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = java_package_; + java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void FileOptions::set_allocated_java_package(::std::string* java_package) { + if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete java_package_; + } + if (java_package) { + set_has_java_package(); + java_package_ = java_package; + } else { + clear_has_java_package(); + java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package) +} // optional string java_outer_classname = 8; inline bool FileOptions::has_java_outer_classname() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FileOptions::set_has_java_outer_classname() { + _has_bits_[0] |= 0x00000002u; +} +inline void FileOptions::clear_has_java_outer_classname() { + _has_bits_[0] &= ~0x00000002u; } inline void FileOptions::clear_java_outer_classname() { - if (java_outer_classname_ != &_default_java_outer_classname_) { + if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_outer_classname_->clear(); } - _clear_bit(1); + clear_has_java_outer_classname(); } inline const ::std::string& FileOptions::java_outer_classname() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname) return *java_outer_classname_; } inline void FileOptions::set_java_outer_classname(const ::std::string& value) { - _set_bit(1); - if (java_outer_classname_ == &_default_java_outer_classname_) { + set_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_outer_classname_ = new ::std::string; } java_outer_classname_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname) } inline void FileOptions::set_java_outer_classname(const char* value) { - _set_bit(1); - if (java_outer_classname_ == &_default_java_outer_classname_) { + set_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_outer_classname_ = new ::std::string; } java_outer_classname_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname) } inline void FileOptions::set_java_outer_classname(const char* value, size_t size) { - _set_bit(1); - if (java_outer_classname_ == &_default_java_outer_classname_) { + set_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_outer_classname_ = new ::std::string; } java_outer_classname_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname) } inline ::std::string* FileOptions::mutable_java_outer_classname() { - _set_bit(1); - if (java_outer_classname_ == &_default_java_outer_classname_) { + set_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_outer_classname_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname) return java_outer_classname_; } +inline ::std::string* FileOptions::release_java_outer_classname() { + clear_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = java_outer_classname_; + java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) { + if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete java_outer_classname_; + } + if (java_outer_classname) { + set_has_java_outer_classname(); + java_outer_classname_ = java_outer_classname; + } else { + clear_has_java_outer_classname(); + java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname) +} // optional bool java_multiple_files = 10 [default = false]; inline bool FileOptions::has_java_multiple_files() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void FileOptions::set_has_java_multiple_files() { + _has_bits_[0] |= 0x00000004u; +} +inline void FileOptions::clear_has_java_multiple_files() { + _has_bits_[0] &= ~0x00000004u; } inline void FileOptions::clear_java_multiple_files() { java_multiple_files_ = false; - _clear_bit(2); + clear_has_java_multiple_files(); } inline bool FileOptions::java_multiple_files() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_multiple_files) return java_multiple_files_; } inline void FileOptions::set_java_multiple_files(bool value) { - _set_bit(2); + set_has_java_multiple_files(); java_multiple_files_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_multiple_files) +} + +// optional bool java_generate_equals_and_hash = 20 [default = false]; +inline bool FileOptions::has_java_generate_equals_and_hash() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void FileOptions::set_has_java_generate_equals_and_hash() { + _has_bits_[0] |= 0x00000008u; +} +inline void FileOptions::clear_has_java_generate_equals_and_hash() { + _has_bits_[0] &= ~0x00000008u; +} +inline void FileOptions::clear_java_generate_equals_and_hash() { + java_generate_equals_and_hash_ = false; + clear_has_java_generate_equals_and_hash(); +} +inline bool FileOptions::java_generate_equals_and_hash() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generate_equals_and_hash) + return java_generate_equals_and_hash_; +} +inline void FileOptions::set_java_generate_equals_and_hash(bool value) { + set_has_java_generate_equals_and_hash(); + java_generate_equals_and_hash_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generate_equals_and_hash) +} + +// optional bool java_string_check_utf8 = 27 [default = false]; +inline bool FileOptions::has_java_string_check_utf8() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void FileOptions::set_has_java_string_check_utf8() { + _has_bits_[0] |= 0x00000010u; +} +inline void FileOptions::clear_has_java_string_check_utf8() { + _has_bits_[0] &= ~0x00000010u; +} +inline void FileOptions::clear_java_string_check_utf8() { + java_string_check_utf8_ = false; + clear_has_java_string_check_utf8(); +} +inline bool FileOptions::java_string_check_utf8() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_string_check_utf8) + return java_string_check_utf8_; +} +inline void FileOptions::set_java_string_check_utf8(bool value) { + set_has_java_string_check_utf8(); + java_string_check_utf8_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_string_check_utf8) } // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; inline bool FileOptions::has_optimize_for() const { - return _has_bit(3); + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void FileOptions::set_has_optimize_for() { + _has_bits_[0] |= 0x00000020u; +} +inline void FileOptions::clear_has_optimize_for() { + _has_bits_[0] &= ~0x00000020u; } inline void FileOptions::clear_optimize_for() { optimize_for_ = 1; - _clear_bit(3); + clear_has_optimize_for(); } inline ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.optimize_for) return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_); } inline void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) { - GOOGLE_DCHECK(::google::protobuf::FileOptions_OptimizeMode_IsValid(value)); - _set_bit(3); + assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value)); + set_has_optimize_for(); optimize_for_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.optimize_for) +} + +// optional string go_package = 11; +inline bool FileOptions::has_go_package() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void FileOptions::set_has_go_package() { + _has_bits_[0] |= 0x00000040u; +} +inline void FileOptions::clear_has_go_package() { + _has_bits_[0] &= ~0x00000040u; +} +inline void FileOptions::clear_go_package() { + if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + go_package_->clear(); + } + clear_has_go_package(); +} +inline const ::std::string& FileOptions::go_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package) + return *go_package_; +} +inline void FileOptions::set_go_package(const ::std::string& value) { + set_has_go_package(); + if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + go_package_ = new ::std::string; + } + go_package_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package) +} +inline void FileOptions::set_go_package(const char* value) { + set_has_go_package(); + if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + go_package_ = new ::std::string; + } + go_package_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package) +} +inline void FileOptions::set_go_package(const char* value, size_t size) { + set_has_go_package(); + if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + go_package_ = new ::std::string; + } + go_package_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package) +} +inline ::std::string* FileOptions::mutable_go_package() { + set_has_go_package(); + if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + go_package_ = new ::std::string; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package) + return go_package_; +} +inline ::std::string* FileOptions::release_go_package() { + clear_has_go_package(); + if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = go_package_; + go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void FileOptions::set_allocated_go_package(::std::string* go_package) { + if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete go_package_; + } + if (go_package) { + set_has_go_package(); + go_package_ = go_package; + } else { + clear_has_go_package(); + go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package) } -// optional bool cc_generic_services = 16 [default = true]; +// optional bool cc_generic_services = 16 [default = false]; inline bool FileOptions::has_cc_generic_services() const { - return _has_bit(4); + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void FileOptions::set_has_cc_generic_services() { + _has_bits_[0] |= 0x00000080u; +} +inline void FileOptions::clear_has_cc_generic_services() { + _has_bits_[0] &= ~0x00000080u; } inline void FileOptions::clear_cc_generic_services() { - cc_generic_services_ = true; - _clear_bit(4); + cc_generic_services_ = false; + clear_has_cc_generic_services(); } inline bool FileOptions::cc_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_generic_services) return cc_generic_services_; } inline void FileOptions::set_cc_generic_services(bool value) { - _set_bit(4); + set_has_cc_generic_services(); cc_generic_services_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_generic_services) } -// optional bool java_generic_services = 17 [default = true]; +// optional bool java_generic_services = 17 [default = false]; inline bool FileOptions::has_java_generic_services() const { - return _has_bit(5); + return (_has_bits_[0] & 0x00000100u) != 0; +} +inline void FileOptions::set_has_java_generic_services() { + _has_bits_[0] |= 0x00000100u; +} +inline void FileOptions::clear_has_java_generic_services() { + _has_bits_[0] &= ~0x00000100u; } inline void FileOptions::clear_java_generic_services() { - java_generic_services_ = true; - _clear_bit(5); + java_generic_services_ = false; + clear_has_java_generic_services(); } inline bool FileOptions::java_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generic_services) return java_generic_services_; } inline void FileOptions::set_java_generic_services(bool value) { - _set_bit(5); + set_has_java_generic_services(); java_generic_services_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generic_services) } -// optional bool py_generic_services = 18 [default = true]; +// optional bool py_generic_services = 18 [default = false]; inline bool FileOptions::has_py_generic_services() const { - return _has_bit(6); + return (_has_bits_[0] & 0x00000200u) != 0; +} +inline void FileOptions::set_has_py_generic_services() { + _has_bits_[0] |= 0x00000200u; +} +inline void FileOptions::clear_has_py_generic_services() { + _has_bits_[0] &= ~0x00000200u; } inline void FileOptions::clear_py_generic_services() { - py_generic_services_ = true; - _clear_bit(6); + py_generic_services_ = false; + clear_has_py_generic_services(); } inline bool FileOptions::py_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.py_generic_services) return py_generic_services_; } inline void FileOptions::set_py_generic_services(bool value) { - _set_bit(6); + set_has_py_generic_services(); py_generic_services_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services) +} + +// optional bool deprecated = 23 [default = false]; +inline bool FileOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000400u) != 0; +} +inline void FileOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000400u; +} +inline void FileOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000400u; +} +inline void FileOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool FileOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.deprecated) + return deprecated_; +} +inline void FileOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.deprecated) } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; @@ -3782,20 +5418,25 @@ inline void FileOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& FileOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* FileOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -3805,34 +5446,74 @@ FileOptions::mutable_uninterpreted_option() { // optional bool message_set_wire_format = 1 [default = false]; inline bool MessageOptions::has_message_set_wire_format() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void MessageOptions::set_has_message_set_wire_format() { + _has_bits_[0] |= 0x00000001u; +} +inline void MessageOptions::clear_has_message_set_wire_format() { + _has_bits_[0] &= ~0x00000001u; } inline void MessageOptions::clear_message_set_wire_format() { message_set_wire_format_ = false; - _clear_bit(0); + clear_has_message_set_wire_format(); } inline bool MessageOptions::message_set_wire_format() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.message_set_wire_format) return message_set_wire_format_; } inline void MessageOptions::set_message_set_wire_format(bool value) { - _set_bit(0); + set_has_message_set_wire_format(); message_set_wire_format_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.message_set_wire_format) } // optional bool no_standard_descriptor_accessor = 2 [default = false]; inline bool MessageOptions::has_no_standard_descriptor_accessor() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void MessageOptions::set_has_no_standard_descriptor_accessor() { + _has_bits_[0] |= 0x00000002u; +} +inline void MessageOptions::clear_has_no_standard_descriptor_accessor() { + _has_bits_[0] &= ~0x00000002u; } inline void MessageOptions::clear_no_standard_descriptor_accessor() { no_standard_descriptor_accessor_ = false; - _clear_bit(1); + clear_has_no_standard_descriptor_accessor(); } inline bool MessageOptions::no_standard_descriptor_accessor() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.no_standard_descriptor_accessor) return no_standard_descriptor_accessor_; } inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) { - _set_bit(1); + set_has_no_standard_descriptor_accessor(); no_standard_descriptor_accessor_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.no_standard_descriptor_accessor) +} + +// optional bool deprecated = 3 [default = false]; +inline bool MessageOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void MessageOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000004u; +} +inline void MessageOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000004u; +} +inline void MessageOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool MessageOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.deprecated) + return deprecated_; +} +inline void MessageOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated) } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; @@ -3843,20 +5524,25 @@ inline void MessageOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& MessageOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* MessageOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -3866,94 +5552,200 @@ MessageOptions::mutable_uninterpreted_option() { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; inline bool FieldOptions::has_ctype() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FieldOptions::set_has_ctype() { + _has_bits_[0] |= 0x00000001u; +} +inline void FieldOptions::clear_has_ctype() { + _has_bits_[0] &= ~0x00000001u; } inline void FieldOptions::clear_ctype() { ctype_ = 0; - _clear_bit(0); + clear_has_ctype(); } inline ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.ctype) return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_); } inline void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) { - GOOGLE_DCHECK(::google::protobuf::FieldOptions_CType_IsValid(value)); - _set_bit(0); + assert(::google::protobuf::FieldOptions_CType_IsValid(value)); + set_has_ctype(); ctype_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.ctype) } // optional bool packed = 2; inline bool FieldOptions::has_packed() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FieldOptions::set_has_packed() { + _has_bits_[0] |= 0x00000002u; +} +inline void FieldOptions::clear_has_packed() { + _has_bits_[0] &= ~0x00000002u; } inline void FieldOptions::clear_packed() { packed_ = false; - _clear_bit(1); + clear_has_packed(); } inline bool FieldOptions::packed() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.packed) return packed_; } inline void FieldOptions::set_packed(bool value) { - _set_bit(1); + set_has_packed(); packed_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed) +} + +// optional bool lazy = 5 [default = false]; +inline bool FieldOptions::has_lazy() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void FieldOptions::set_has_lazy() { + _has_bits_[0] |= 0x00000004u; +} +inline void FieldOptions::clear_has_lazy() { + _has_bits_[0] &= ~0x00000004u; +} +inline void FieldOptions::clear_lazy() { + lazy_ = false; + clear_has_lazy(); +} +inline bool FieldOptions::lazy() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.lazy) + return lazy_; +} +inline void FieldOptions::set_lazy(bool value) { + set_has_lazy(); + lazy_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.lazy) } // optional bool deprecated = 3 [default = false]; inline bool FieldOptions::has_deprecated() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void FieldOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000008u; +} +inline void FieldOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000008u; } inline void FieldOptions::clear_deprecated() { deprecated_ = false; - _clear_bit(2); + clear_has_deprecated(); } inline bool FieldOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.deprecated) return deprecated_; } inline void FieldOptions::set_deprecated(bool value) { - _set_bit(2); + set_has_deprecated(); deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated) } // optional string experimental_map_key = 9; inline bool FieldOptions::has_experimental_map_key() const { - return _has_bit(3); + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void FieldOptions::set_has_experimental_map_key() { + _has_bits_[0] |= 0x00000010u; +} +inline void FieldOptions::clear_has_experimental_map_key() { + _has_bits_[0] &= ~0x00000010u; } inline void FieldOptions::clear_experimental_map_key() { - if (experimental_map_key_ != &_default_experimental_map_key_) { + if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { experimental_map_key_->clear(); } - _clear_bit(3); + clear_has_experimental_map_key(); } inline const ::std::string& FieldOptions::experimental_map_key() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.experimental_map_key) return *experimental_map_key_; } inline void FieldOptions::set_experimental_map_key(const ::std::string& value) { - _set_bit(3); - if (experimental_map_key_ == &_default_experimental_map_key_) { + set_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { experimental_map_key_ = new ::std::string; } experimental_map_key_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.experimental_map_key) } inline void FieldOptions::set_experimental_map_key(const char* value) { - _set_bit(3); - if (experimental_map_key_ == &_default_experimental_map_key_) { + set_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { experimental_map_key_ = new ::std::string; } experimental_map_key_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldOptions.experimental_map_key) } inline void FieldOptions::set_experimental_map_key(const char* value, size_t size) { - _set_bit(3); - if (experimental_map_key_ == &_default_experimental_map_key_) { + set_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { experimental_map_key_ = new ::std::string; } experimental_map_key_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldOptions.experimental_map_key) } inline ::std::string* FieldOptions::mutable_experimental_map_key() { - _set_bit(3); - if (experimental_map_key_ == &_default_experimental_map_key_) { + set_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { experimental_map_key_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.experimental_map_key) return experimental_map_key_; } +inline ::std::string* FieldOptions::release_experimental_map_key() { + clear_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = experimental_map_key_; + experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void FieldOptions::set_allocated_experimental_map_key(::std::string* experimental_map_key) { + if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete experimental_map_key_; + } + if (experimental_map_key) { + set_has_experimental_map_key(); + experimental_map_key_ = experimental_map_key; + } else { + clear_has_experimental_map_key(); + experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldOptions.experimental_map_key) +} + +// optional bool weak = 10 [default = false]; +inline bool FieldOptions::has_weak() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void FieldOptions::set_has_weak() { + _has_bits_[0] |= 0x00000020u; +} +inline void FieldOptions::clear_has_weak() { + _has_bits_[0] &= ~0x00000020u; +} +inline void FieldOptions::clear_weak() { + weak_ = false; + clear_has_weak(); +} +inline bool FieldOptions::weak() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak) + return weak_; +} +inline void FieldOptions::set_weak(bool value) { + set_has_weak(); + weak_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak) +} // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int FieldOptions::uninterpreted_option_size() const { @@ -3963,20 +5755,25 @@ inline void FieldOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& FieldOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* FieldOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -3984,6 +5781,54 @@ FieldOptions::mutable_uninterpreted_option() { // EnumOptions +// optional bool allow_alias = 2; +inline bool EnumOptions::has_allow_alias() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void EnumOptions::set_has_allow_alias() { + _has_bits_[0] |= 0x00000001u; +} +inline void EnumOptions::clear_has_allow_alias() { + _has_bits_[0] &= ~0x00000001u; +} +inline void EnumOptions::clear_allow_alias() { + allow_alias_ = false; + clear_has_allow_alias(); +} +inline bool EnumOptions::allow_alias() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.allow_alias) + return allow_alias_; +} +inline void EnumOptions::set_allow_alias(bool value) { + set_has_allow_alias(); + allow_alias_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.allow_alias) +} + +// optional bool deprecated = 3 [default = false]; +inline bool EnumOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void EnumOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000002u; +} +inline void EnumOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000002u; +} +inline void EnumOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool EnumOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.deprecated) + return deprecated_; +} +inline void EnumOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.deprecated) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int EnumOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); @@ -3992,20 +5837,25 @@ inline void EnumOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& EnumOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* EnumOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -4013,6 +5863,30 @@ EnumOptions::mutable_uninterpreted_option() { // EnumValueOptions +// optional bool deprecated = 1 [default = false]; +inline bool EnumValueOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void EnumValueOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000001u; +} +inline void EnumValueOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000001u; +} +inline void EnumValueOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool EnumValueOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated) + return deprecated_; +} +inline void EnumValueOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int EnumValueOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); @@ -4021,20 +5895,25 @@ inline void EnumValueOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& EnumValueOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* EnumValueOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -4042,6 +5921,30 @@ EnumValueOptions::mutable_uninterpreted_option() { // ServiceOptions +// optional bool deprecated = 33 [default = false]; +inline bool ServiceOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ServiceOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000001u; +} +inline void ServiceOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ServiceOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool ServiceOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.deprecated) + return deprecated_; +} +inline void ServiceOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.ServiceOptions.deprecated) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int ServiceOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); @@ -4050,20 +5953,25 @@ inline void ServiceOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& ServiceOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* ServiceOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -4071,6 +5979,30 @@ ServiceOptions::mutable_uninterpreted_option() { // MethodOptions +// optional bool deprecated = 33 [default = false]; +inline bool MethodOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void MethodOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000001u; +} +inline void MethodOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000001u; +} +inline void MethodOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool MethodOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.deprecated) + return deprecated_; +} +inline void MethodOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.deprecated) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int MethodOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); @@ -4079,20 +6011,25 @@ inline void MethodOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& MethodOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* MethodOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -4102,60 +6039,102 @@ MethodOptions::mutable_uninterpreted_option() { // required string name_part = 1; inline bool UninterpretedOption_NamePart::has_name_part() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void UninterpretedOption_NamePart::set_has_name_part() { + _has_bits_[0] |= 0x00000001u; +} +inline void UninterpretedOption_NamePart::clear_has_name_part() { + _has_bits_[0] &= ~0x00000001u; } inline void UninterpretedOption_NamePart::clear_name_part() { - if (name_part_ != &_default_name_part_) { + if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_part_->clear(); } - _clear_bit(0); + clear_has_name_part(); } inline const ::std::string& UninterpretedOption_NamePart::name_part() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part) return *name_part_; } inline void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) { - _set_bit(0); - if (name_part_ == &_default_name_part_) { + set_has_name_part(); + if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_part_ = new ::std::string; } name_part_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part) } inline void UninterpretedOption_NamePart::set_name_part(const char* value) { - _set_bit(0); - if (name_part_ == &_default_name_part_) { + set_has_name_part(); + if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_part_ = new ::std::string; } name_part_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part) } inline void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) { - _set_bit(0); - if (name_part_ == &_default_name_part_) { + set_has_name_part(); + if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_part_ = new ::std::string; } name_part_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part) } inline ::std::string* UninterpretedOption_NamePart::mutable_name_part() { - _set_bit(0); - if (name_part_ == &_default_name_part_) { + set_has_name_part(); + if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_part_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part) return name_part_; } +inline ::std::string* UninterpretedOption_NamePart::release_name_part() { + clear_has_name_part(); + if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = name_part_; + name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) { + if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_part_; + } + if (name_part) { + set_has_name_part(); + name_part_ = name_part; + } else { + clear_has_name_part(); + name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part) +} // required bool is_extension = 2; inline bool UninterpretedOption_NamePart::has_is_extension() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void UninterpretedOption_NamePart::set_has_is_extension() { + _has_bits_[0] |= 0x00000002u; +} +inline void UninterpretedOption_NamePart::clear_has_is_extension() { + _has_bits_[0] &= ~0x00000002u; } inline void UninterpretedOption_NamePart::clear_is_extension() { is_extension_ = false; - _clear_bit(1); + clear_has_is_extension(); } inline bool UninterpretedOption_NamePart::is_extension() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.is_extension) return is_extension_; } inline void UninterpretedOption_NamePart::set_is_extension(bool value) { - _set_bit(1); + set_has_is_extension(); is_extension_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension) } // ------------------------------------------------------------------- @@ -4170,154 +6149,577 @@ inline void UninterpretedOption::clear_name() { name_.Clear(); } inline const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name) return name_.Get(index); } inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name) return name_.Mutable(index); } inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() { + // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name) return name_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& UninterpretedOption::name() const { + // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name) return name_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* UninterpretedOption::mutable_name() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name) return &name_; } // optional string identifier_value = 3; inline bool UninterpretedOption::has_identifier_value() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void UninterpretedOption::set_has_identifier_value() { + _has_bits_[0] |= 0x00000002u; +} +inline void UninterpretedOption::clear_has_identifier_value() { + _has_bits_[0] &= ~0x00000002u; } inline void UninterpretedOption::clear_identifier_value() { - if (identifier_value_ != &_default_identifier_value_) { + if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { identifier_value_->clear(); } - _clear_bit(1); + clear_has_identifier_value(); } inline const ::std::string& UninterpretedOption::identifier_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value) return *identifier_value_; } inline void UninterpretedOption::set_identifier_value(const ::std::string& value) { - _set_bit(1); - if (identifier_value_ == &_default_identifier_value_) { + set_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { identifier_value_ = new ::std::string; } identifier_value_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value) } inline void UninterpretedOption::set_identifier_value(const char* value) { - _set_bit(1); - if (identifier_value_ == &_default_identifier_value_) { + set_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { identifier_value_ = new ::std::string; } identifier_value_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value) } inline void UninterpretedOption::set_identifier_value(const char* value, size_t size) { - _set_bit(1); - if (identifier_value_ == &_default_identifier_value_) { + set_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { identifier_value_ = new ::std::string; } identifier_value_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value) } inline ::std::string* UninterpretedOption::mutable_identifier_value() { - _set_bit(1); - if (identifier_value_ == &_default_identifier_value_) { + set_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { identifier_value_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value) return identifier_value_; } +inline ::std::string* UninterpretedOption::release_identifier_value() { + clear_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = identifier_value_; + identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) { + if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete identifier_value_; + } + if (identifier_value) { + set_has_identifier_value(); + identifier_value_ = identifier_value; + } else { + clear_has_identifier_value(); + identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value) +} // optional uint64 positive_int_value = 4; inline bool UninterpretedOption::has_positive_int_value() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void UninterpretedOption::set_has_positive_int_value() { + _has_bits_[0] |= 0x00000004u; +} +inline void UninterpretedOption::clear_has_positive_int_value() { + _has_bits_[0] &= ~0x00000004u; } inline void UninterpretedOption::clear_positive_int_value() { positive_int_value_ = GOOGLE_ULONGLONG(0); - _clear_bit(2); + clear_has_positive_int_value(); } inline ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value) return positive_int_value_; } inline void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) { - _set_bit(2); + set_has_positive_int_value(); positive_int_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value) } // optional int64 negative_int_value = 5; inline bool UninterpretedOption::has_negative_int_value() const { - return _has_bit(3); + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void UninterpretedOption::set_has_negative_int_value() { + _has_bits_[0] |= 0x00000008u; +} +inline void UninterpretedOption::clear_has_negative_int_value() { + _has_bits_[0] &= ~0x00000008u; } inline void UninterpretedOption::clear_negative_int_value() { negative_int_value_ = GOOGLE_LONGLONG(0); - _clear_bit(3); + clear_has_negative_int_value(); } inline ::google::protobuf::int64 UninterpretedOption::negative_int_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value) return negative_int_value_; } inline void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) { - _set_bit(3); + set_has_negative_int_value(); negative_int_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value) } // optional double double_value = 6; inline bool UninterpretedOption::has_double_value() const { - return _has_bit(4); + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void UninterpretedOption::set_has_double_value() { + _has_bits_[0] |= 0x00000010u; +} +inline void UninterpretedOption::clear_has_double_value() { + _has_bits_[0] &= ~0x00000010u; } inline void UninterpretedOption::clear_double_value() { double_value_ = 0; - _clear_bit(4); + clear_has_double_value(); } inline double UninterpretedOption::double_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.double_value) return double_value_; } inline void UninterpretedOption::set_double_value(double value) { - _set_bit(4); + set_has_double_value(); double_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value) } // optional bytes string_value = 7; inline bool UninterpretedOption::has_string_value() const { - return _has_bit(5); + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void UninterpretedOption::set_has_string_value() { + _has_bits_[0] |= 0x00000020u; +} +inline void UninterpretedOption::clear_has_string_value() { + _has_bits_[0] &= ~0x00000020u; } inline void UninterpretedOption::clear_string_value() { - if (string_value_ != &_default_string_value_) { + if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { string_value_->clear(); } - _clear_bit(5); + clear_has_string_value(); } inline const ::std::string& UninterpretedOption::string_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value) return *string_value_; } inline void UninterpretedOption::set_string_value(const ::std::string& value) { - _set_bit(5); - if (string_value_ == &_default_string_value_) { + set_has_string_value(); + if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { string_value_ = new ::std::string; } string_value_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value) } inline void UninterpretedOption::set_string_value(const char* value) { - _set_bit(5); - if (string_value_ == &_default_string_value_) { + set_has_string_value(); + if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { string_value_ = new ::std::string; } string_value_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value) } inline void UninterpretedOption::set_string_value(const void* value, size_t size) { - _set_bit(5); - if (string_value_ == &_default_string_value_) { + set_has_string_value(); + if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { string_value_ = new ::std::string; } string_value_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value) } inline ::std::string* UninterpretedOption::mutable_string_value() { - _set_bit(5); - if (string_value_ == &_default_string_value_) { + set_has_string_value(); + if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { string_value_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value) return string_value_; } +inline ::std::string* UninterpretedOption::release_string_value() { + clear_has_string_value(); + if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = string_value_; + string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void UninterpretedOption::set_allocated_string_value(::std::string* string_value) { + if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete string_value_; + } + if (string_value) { + set_has_string_value(); + string_value_ = string_value; + } else { + clear_has_string_value(); + string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value) +} + +// optional string aggregate_value = 8; +inline bool UninterpretedOption::has_aggregate_value() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void UninterpretedOption::set_has_aggregate_value() { + _has_bits_[0] |= 0x00000040u; +} +inline void UninterpretedOption::clear_has_aggregate_value() { + _has_bits_[0] &= ~0x00000040u; +} +inline void UninterpretedOption::clear_aggregate_value() { + if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + aggregate_value_->clear(); + } + clear_has_aggregate_value(); +} +inline const ::std::string& UninterpretedOption::aggregate_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value) + return *aggregate_value_; +} +inline void UninterpretedOption::set_aggregate_value(const ::std::string& value) { + set_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + aggregate_value_ = new ::std::string; + } + aggregate_value_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value) +} +inline void UninterpretedOption::set_aggregate_value(const char* value) { + set_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + aggregate_value_ = new ::std::string; + } + aggregate_value_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value) +} +inline void UninterpretedOption::set_aggregate_value(const char* value, size_t size) { + set_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + aggregate_value_ = new ::std::string; + } + aggregate_value_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value) +} +inline ::std::string* UninterpretedOption::mutable_aggregate_value() { + set_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + aggregate_value_ = new ::std::string; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value) + return aggregate_value_; +} +inline ::std::string* UninterpretedOption::release_aggregate_value() { + clear_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = aggregate_value_; + aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) { + if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete aggregate_value_; + } + if (aggregate_value) { + set_has_aggregate_value(); + aggregate_value_ = aggregate_value; + } else { + clear_has_aggregate_value(); + aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value) +} + +// ------------------------------------------------------------------- + +// SourceCodeInfo_Location + +// repeated int32 path = 1 [packed = true]; +inline int SourceCodeInfo_Location::path_size() const { + return path_.size(); +} +inline void SourceCodeInfo_Location::clear_path() { + path_.Clear(); +} +inline ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path) + return path_.Get(index); +} +inline void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) { + path_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path) +} +inline void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) { + path_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path) +} +inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +SourceCodeInfo_Location::path() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path) + return path_; +} +inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +SourceCodeInfo_Location::mutable_path() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path) + return &path_; +} + +// repeated int32 span = 2 [packed = true]; +inline int SourceCodeInfo_Location::span_size() const { + return span_.size(); +} +inline void SourceCodeInfo_Location::clear_span() { + span_.Clear(); +} +inline ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span) + return span_.Get(index); +} +inline void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) { + span_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span) +} +inline void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) { + span_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span) +} +inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +SourceCodeInfo_Location::span() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span) + return span_; +} +inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +SourceCodeInfo_Location::mutable_span() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span) + return &span_; +} + +// optional string leading_comments = 3; +inline bool SourceCodeInfo_Location::has_leading_comments() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void SourceCodeInfo_Location::set_has_leading_comments() { + _has_bits_[0] |= 0x00000004u; +} +inline void SourceCodeInfo_Location::clear_has_leading_comments() { + _has_bits_[0] &= ~0x00000004u; +} +inline void SourceCodeInfo_Location::clear_leading_comments() { + if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + leading_comments_->clear(); + } + clear_has_leading_comments(); +} +inline const ::std::string& SourceCodeInfo_Location::leading_comments() const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments) + return *leading_comments_; +} +inline void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) { + set_has_leading_comments(); + if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + leading_comments_ = new ::std::string; + } + leading_comments_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments) +} +inline void SourceCodeInfo_Location::set_leading_comments(const char* value) { + set_has_leading_comments(); + if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + leading_comments_ = new ::std::string; + } + leading_comments_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments) +} +inline void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) { + set_has_leading_comments(); + if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + leading_comments_ = new ::std::string; + } + leading_comments_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments) +} +inline ::std::string* SourceCodeInfo_Location::mutable_leading_comments() { + set_has_leading_comments(); + if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + leading_comments_ = new ::std::string; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments) + return leading_comments_; +} +inline ::std::string* SourceCodeInfo_Location::release_leading_comments() { + clear_has_leading_comments(); + if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = leading_comments_; + leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) { + if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete leading_comments_; + } + if (leading_comments) { + set_has_leading_comments(); + leading_comments_ = leading_comments; + } else { + clear_has_leading_comments(); + leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments) +} + +// optional string trailing_comments = 4; +inline bool SourceCodeInfo_Location::has_trailing_comments() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void SourceCodeInfo_Location::set_has_trailing_comments() { + _has_bits_[0] |= 0x00000008u; +} +inline void SourceCodeInfo_Location::clear_has_trailing_comments() { + _has_bits_[0] &= ~0x00000008u; +} +inline void SourceCodeInfo_Location::clear_trailing_comments() { + if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + trailing_comments_->clear(); + } + clear_has_trailing_comments(); +} +inline const ::std::string& SourceCodeInfo_Location::trailing_comments() const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments) + return *trailing_comments_; +} +inline void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) { + set_has_trailing_comments(); + if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + trailing_comments_ = new ::std::string; + } + trailing_comments_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} +inline void SourceCodeInfo_Location::set_trailing_comments(const char* value) { + set_has_trailing_comments(); + if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + trailing_comments_ = new ::std::string; + } + trailing_comments_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} +inline void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) { + set_has_trailing_comments(); + if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + trailing_comments_ = new ::std::string; + } + trailing_comments_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} +inline ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() { + set_has_trailing_comments(); + if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + trailing_comments_ = new ::std::string; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments) + return trailing_comments_; +} +inline ::std::string* SourceCodeInfo_Location::release_trailing_comments() { + clear_has_trailing_comments(); + if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = trailing_comments_; + trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) { + if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete trailing_comments_; + } + if (trailing_comments) { + set_has_trailing_comments(); + trailing_comments_ = trailing_comments; + } else { + clear_has_trailing_comments(); + trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} + +// ------------------------------------------------------------------- + +// SourceCodeInfo + +// repeated .google.protobuf.SourceCodeInfo.Location location = 1; +inline int SourceCodeInfo::location_size() const { + return location_.size(); +} +inline void SourceCodeInfo::clear_location() { + location_.Clear(); +} +inline const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location) + return location_.Get(index); +} +inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location) + return location_.Mutable(index); +} +inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() { + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location) + return location_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& +SourceCodeInfo::location() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location) + return location_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* +SourceCodeInfo::mutable_location() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location) + return &location_; +} // @@protoc_insertion_point(namespace_scope) @@ -4329,18 +6731,22 @@ inline ::std::string* UninterpretedOption::mutable_string_value() { namespace google { namespace protobuf { +template <> struct is_proto_enum< ::google::protobuf::FieldDescriptorProto_Type> : ::google::protobuf::internal::true_type {}; template <> inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Type>() { return ::google::protobuf::FieldDescriptorProto_Type_descriptor(); } +template <> struct is_proto_enum< ::google::protobuf::FieldDescriptorProto_Label> : ::google::protobuf::internal::true_type {}; template <> inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Label>() { return ::google::protobuf::FieldDescriptorProto_Label_descriptor(); } +template <> struct is_proto_enum< ::google::protobuf::FileOptions_OptimizeMode> : ::google::protobuf::internal::true_type {}; template <> inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FileOptions_OptimizeMode>() { return ::google::protobuf::FileOptions_OptimizeMode_descriptor(); } +template <> struct is_proto_enum< ::google::protobuf::FieldOptions_CType> : ::google::protobuf::internal::true_type {}; template <> inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_CType>() { return ::google::protobuf::FieldOptions_CType_descriptor(); diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index cc04aa8..4514164 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -59,6 +59,11 @@ message FileDescriptorProto { // Names of files imported by this file. repeated string dependency = 3; + // Indexes of the public imported files in the dependency list above. + repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + repeated int32 weak_dependency = 11; // All top-level definitions in this file. repeated DescriptorProto message_type = 4; @@ -67,6 +72,12 @@ message FileDescriptorProto { repeated FieldDescriptorProto extension = 7; optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field whithout harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; } // Describes a message type. @@ -85,6 +96,8 @@ message DescriptorProto { } repeated ExtensionRange extension_range = 5; + repeated OneofDescriptorProto oneof_decl = 8; + optional MessageOptions options = 7; } @@ -95,13 +108,13 @@ message FieldDescriptorProto { // Order is weird for historical reasons. TYPE_DOUBLE = 1; TYPE_FLOAT = 2; - TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT64 if negative - // values are likely. + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + TYPE_INT64 = 3; TYPE_UINT64 = 4; - TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT32 if negative - // values are likely. + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + TYPE_INT32 = 5; TYPE_FIXED64 = 6; TYPE_FIXED32 = 7; TYPE_BOOL = 8; @@ -132,7 +145,7 @@ message FieldDescriptorProto { optional Label label = 4; // If type_name is set, this need not be set. If both this and type_name - // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. optional Type type = 5; // For message and enum types, this is the name of the type. If the name @@ -153,9 +166,20 @@ message FieldDescriptorProto { // TODO(kenton): Base-64 encode? optional string default_value = 7; + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. Extensions of a oneof should + // not set this since the oneof to which they belong will be inferred based + // on the extension range containing the extension's field number. + optional int32 oneof_index = 9; + optional FieldOptions options = 8; } +// Describes a oneof. +message OneofDescriptorProto { + optional string name = 1; +} + // Describes an enum type. message EnumDescriptorProto { optional string name = 1; @@ -193,6 +217,7 @@ message MethodDescriptorProto { optional MethodOptions options = 4; } + // =================================================================== // Options @@ -214,10 +239,15 @@ message MethodDescriptorProto { // through 99999. It is up to you to ensure that you do not use the // same number for multiple options. // * For options which will be published and used publicly by multiple -// independent entities, e-mail kenton@google.com to reserve extension -// numbers. Simply tell me how many you need and I'll send you back a -// set of numbers to use -- there's no need to explain how you intend to -// use them. If this turns out to be popular, a web service will be set up +// independent entities, e-mail protobuf-global-extension-registry@google.com +// to reserve extension numbers. Simply provide your project name (e.g. +// Object-C plugin) and your porject website (if available) -- there's no need +// to explain how you intend to use them. Usually you only need one extension +// number. You can declare multiple options with only one extension number by +// putting them in a sub-message. See the Custom Options section of the docs +// for examples: +// http://code.google.com/apis/protocolbuffers/docs/proto.html#options +// If this turns out to be popular, a web service will be set up // to automatically assign option numbers. @@ -245,6 +275,27 @@ message FileOptions { // top-level extensions defined in the file. optional bool java_multiple_files = 10 [default=false]; + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. + // - In the full runtime, this is purely a speed optimization, as the + // AbstractMessage base class includes reflection-based implementations of + // these methods. + //- In the lite runtime, setting this option changes the semantics of + // equals() and hashCode() to more closely match those of the full runtime; + // the generated methods compute their results based on field values rather + // than object identity. (Implementations should not assume that hashcodes + // will be consistent across runtimes or versions of the protocol compiler.) + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // If set true, then the Java2 code generator will generate code that + // throws an exception whenever an attempt is made to assign a non-UTF-8 + // byte sequence to a string field. + // Message reflection will do the same. + // However, an extension field still accepts non-UTF-8 byte sequences. + // This option has no effect on when used with the lite runtime. + optional bool java_string_check_utf8 = 27 [default=false]; + + // Generated classes can be optimized for speed or code size. enum OptimizeMode { SPEED = 1; // Generate complete code for parsing, serialization, @@ -254,6 +305,9 @@ message FileOptions { } optional OptimizeMode optimize_for = 9 [default=SPEED]; + // Sets the Go package where structs generated from this .proto will be + // placed. There is no default. + optional string go_package = 11; @@ -264,13 +318,19 @@ message FileOptions { // early versions of proto2. // // Generic services are now considered deprecated in favor of using plugins - // that generate code specific to your particular RPC system. If you are - // using such a plugin, set these to false. In the future, we may change - // the default to false, so if you explicitly want generic services, you - // should explicitly set these to true. - optional bool cc_generic_services = 16 [default=true]; - optional bool java_generic_services = 17 [default=true]; - optional bool py_generic_services = 18 [default=true]; + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + optional bool deprecated = 23 [default=false]; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -305,6 +365,12 @@ message MessageOptions { // from proto1 easier; new code should avoid fields named "descriptor". optional bool no_standard_descriptor_accessor = 2 [default=false]; + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default=false]; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -333,6 +399,37 @@ message FieldOptions { optional bool packed = 2; + + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // + // Note that implementations may choose not to check required fields within + // a lazy sub-message. That is, calling IsInitialized() on the outher message + // may return true even if the inner message has missing required fields. + // This is necessary because otherwise the inner message would have to be + // parsed in order to perform the check, defeating the purpose of lazy + // parsing. An implementation which chooses not to check required fields + // must be consistent about it. That is, for any particular sub-message, the + // implementation must either *always* check its required fields, or *never* + // check its required fields, regardless of whether or not the message has + // been parsed. + optional bool lazy = 5 [default=false]; + // Is this field deprecated? // Depending on the target platform, this can emit Deprecated annotations // for accessors, or it will be completely ignored; in the very least, this @@ -353,6 +450,11 @@ message FieldOptions { // TODO: Fully-implement this, then remove the "experimental_" prefix. optional string experimental_map_key = 9; + // For Google-internal migration only. Do not use. + optional bool weak = 10 [default=false]; + + + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -362,6 +464,16 @@ message FieldOptions { message EnumOptions { + // Set this option to true to allow mapping different tag names to the same + // value. + optional bool allow_alias = 2; + + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + optional bool deprecated = 3 [default=false]; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -370,6 +482,12 @@ message EnumOptions { } message EnumValueOptions { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + optional bool deprecated = 1 [default=false]; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -384,6 +502,12 @@ message ServiceOptions { // we were already using them long before we decided to release Protocol // Buffers. + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + optional bool deprecated = 33 [default=false]; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -398,6 +522,12 @@ message MethodOptions { // we were already using them long before we decided to release Protocol // Buffers. + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + optional bool deprecated = 33 [default=false]; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -405,6 +535,7 @@ message MethodOptions { extensions 1000 to max; } + // A message representing a option the parser does not recognize. This only // appears in options protos created by the compiler::Parser class. // DescriptorPool resolves these when building Descriptor objects. Therefore, @@ -430,4 +561,127 @@ message UninterpretedOption { optional int64 negative_int_value = 5; optional double double_value = 6; optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + optional string leading_comments = 3; + optional string trailing_comments = 4; + } } diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc index 95708d9..e5c2536 100644 --- a/src/google/protobuf/descriptor_database.cc +++ b/src/google/protobuf/descriptor_database.cc @@ -39,8 +39,8 @@ #include #include #include -#include -#include +#include +#include namespace google { namespace protobuf { @@ -101,7 +101,7 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddSymbol( if (iter == by_symbol_.end()) { // Apparently the map is currently empty. Just insert and be done with it. - by_symbol_.insert(make_pair(name, value)); + by_symbol_.insert(typename map::value_type(name, value)); return true; } @@ -128,7 +128,7 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddSymbol( // Insert the new symbol using the iterator as a hint, the new entry will // appear immediately before the one the iterator is pointing at. - by_symbol_.insert(iter, make_pair(name, value)); + by_symbol_.insert(iter, typename map::value_type(name, value)); return true; } @@ -289,6 +289,7 @@ bool SimpleDescriptorDatabase::FindAllExtensionNumbers( return index_.FindAllExtensionNumbers(extendee_type, output); } + bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file, FileDescriptorProto* output) { if (file == NULL) return false; @@ -537,5 +538,6 @@ bool MergedDescriptorDatabase::FindAllExtensionNumbers( return success; } + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h index f32b1db..c35e478 100644 --- a/src/google/protobuf/descriptor_database.h +++ b/src/google/protobuf/descriptor_database.h @@ -41,6 +41,7 @@ #include #include #include +#include #include namespace google { @@ -95,11 +96,12 @@ class LIBPROTOBUF_EXPORT DescriptorDatabase { // // This method has a default implementation that always returns // false. - virtual bool FindAllExtensionNumbers(const string& extendee_type, - vector* output) { + virtual bool FindAllExtensionNumbers(const string& /* extendee_type */, + vector* /* output */) { return false; } + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase); }; @@ -355,6 +357,7 @@ class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase { bool FindAllExtensionNumbers(const string& extendee_type, vector* output); + private: vector sources_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MergedDescriptorDatabase); diff --git a/src/google/protobuf/descriptor_pb2_test.py b/src/google/protobuf/descriptor_pb2_test.py new file mode 100644 index 0000000..1c22228 --- /dev/null +++ b/src/google/protobuf/descriptor_pb2_test.py @@ -0,0 +1,54 @@ +#! /usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +# Verify that prebuild and checkedin version of descriptor_pb2.py is up to date. + +from google3.pyglib import resources +import unittest + +_DESC = 'google3/net/proto2/proto/descriptor_pb2.' +_OLD = _DESC + 'py-prebuilt' +_NEW = _DESC + 'compiled' + + +class PregeneratedFileChanged(unittest.TestCase): + + def testSameText(self): + generated = resources.GetResource(_NEW) + checkedin = resources.GetResource(_OLD) + self.assertMultiLineEqual( + generated, checkedin, 'It seems that protoc _pb2 generator changed. ' + 'Please run google/protobuf/generate_descriptor_proto.sh to ' + 'regnerate a new version of %s and add it to your CL' % _OLD) + +if __name__ == '__main__': + unittest.main() diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index ec2c815..9b77fbe 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -36,13 +36,15 @@ #include +#include +#include +#include +#include +#include #include #include #include -#include #include -#include -#include #include #include @@ -644,6 +646,104 @@ TEST_F(DescriptorTest, FieldEnumType) { // =================================================================== +// Test simple flat messages and fields. +class OneofDescriptorTest : public testing::Test { + protected: + virtual void SetUp() { + // Build descriptors for the following definitions: + // + // package garply; + // message TestOneof { + // optional int32 a = 1; + // oneof foo { + // string b = 2; + // TestOneof c = 3; + // } + // oneof bar { + // float d = 4; + // } + // } + + FileDescriptorProto baz_file; + baz_file.set_name("baz.proto"); + baz_file.set_package("garply"); + + DescriptorProto* oneof_message = AddMessage(&baz_file, "TestOneof"); + oneof_message->add_oneof_decl()->set_name("foo"); + oneof_message->add_oneof_decl()->set_name("bar"); + + AddField(oneof_message, "a", 1, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddField(oneof_message, "b", 2, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_STRING); + oneof_message->mutable_field(1)->set_oneof_index(0); + AddField(oneof_message, "c", 3, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_MESSAGE); + oneof_message->mutable_field(2)->set_oneof_index(0); + oneof_message->mutable_field(2)->set_type_name("TestOneof"); + + AddField(oneof_message, "d", 4, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_FLOAT); + oneof_message->mutable_field(3)->set_oneof_index(1); + + // Build the descriptors and get the pointers. + baz_file_ = pool_.BuildFile(baz_file); + ASSERT_TRUE(baz_file_ != NULL); + + ASSERT_EQ(1, baz_file_->message_type_count()); + oneof_message_ = baz_file_->message_type(0); + + ASSERT_EQ(2, oneof_message_->oneof_decl_count()); + oneof_ = oneof_message_->oneof_decl(0); + oneof2_ = oneof_message_->oneof_decl(1); + + ASSERT_EQ(4, oneof_message_->field_count()); + a_ = oneof_message_->field(0); + b_ = oneof_message_->field(1); + c_ = oneof_message_->field(2); + d_ = oneof_message_->field(3); + } + + DescriptorPool pool_; + + const FileDescriptor* baz_file_; + + const Descriptor* oneof_message_; + + const OneofDescriptor* oneof_; + const OneofDescriptor* oneof2_; + const FieldDescriptor* a_; + const FieldDescriptor* b_; + const FieldDescriptor* c_; + const FieldDescriptor* d_; + const FieldDescriptor* e_; + const FieldDescriptor* f_; +}; + +TEST_F(OneofDescriptorTest, Normal) { + EXPECT_EQ("foo", oneof_->name()); + EXPECT_EQ("garply.TestOneof.foo", oneof_->full_name()); + EXPECT_EQ(0, oneof_->index()); + ASSERT_EQ(2, oneof_->field_count()); + EXPECT_EQ(b_, oneof_->field(0)); + EXPECT_EQ(c_, oneof_->field(1)); + EXPECT_TRUE(a_->containing_oneof() == NULL); + EXPECT_EQ(oneof_, b_->containing_oneof()); + EXPECT_EQ(oneof_, c_->containing_oneof()); +} + +TEST_F(OneofDescriptorTest, FindByName) { + EXPECT_EQ(oneof_, oneof_message_->FindOneofByName("foo")); + EXPECT_EQ(oneof2_, oneof_message_->FindOneofByName("bar")); + EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == NULL); +} + +// =================================================================== + class StylizedFieldNamesTest : public testing::Test { protected: void SetUp() { @@ -1514,13 +1614,46 @@ TEST_F(ExtensionDescriptorTest, FindAllExtensions) { EXPECT_EQ(39, extensions[3]->number()); } +TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) { + DescriptorPool pool; + FileDescriptorProto file_proto; + // Add "google/protobuf/descriptor.proto". + FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + // Add "foo.proto": + // import "google/protobuf/descriptor.proto"; + // extend google.protobuf.FieldOptions { + // optional int32 option1 = 1000; + // } + file_proto.Clear(); + file_proto.set_name("foo.proto"); + file_proto.add_dependency("google/protobuf/descriptor.proto"); + AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + // Add "bar.proto": + // import "google/protobuf/descriptor.proto"; + // extend google.protobuf.FieldOptions { + // optional int32 option2 = 1000; + // } + file_proto.Clear(); + file_proto.set_name("bar.proto"); + file_proto.add_dependency("google/protobuf/descriptor.proto"); + AddExtension(&file_proto, "google.protobuf.FieldOptions", "option2", 1000, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + // Currently we only generate a warning for conflicting extension numbers. + // TODO(xiaofeng): Change it to an error. + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); +} + // =================================================================== class MiscTest : public testing::Test { protected: - // Function which makes a field of the given type just to find out what its - // cpp_type is. - FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) { + // Function which makes a field descriptor of the given type. + const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) { FileDescriptorProto file_proto; file_proto.set_name("foo.proto"); AddEmptyEnum(&file_proto, "DummyEnum"); @@ -1538,19 +1671,99 @@ class MiscTest : public testing::Test { } // Build the descriptors and get the pointers. - DescriptorPool pool; - const FileDescriptor* file = pool.BuildFile(file_proto); + pool_.reset(new DescriptorPool()); + const FileDescriptor* file = pool_->BuildFile(file_proto); if (file != NULL && file->message_type_count() == 1 && file->message_type(0)->field_count() == 1) { - return file->message_type(0)->field(0)->cpp_type(); + return file->message_type(0)->field(0); } else { - return static_cast(0); + return NULL; } } + + const char* GetTypeNameForFieldType(FieldDescriptor::Type type) { + const FieldDescriptor* field = GetFieldDescriptorOfType(type); + return field != NULL ? field->type_name() : ""; + } + + FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) { + const FieldDescriptor* field = GetFieldDescriptorOfType(type); + return field != NULL ? field->cpp_type() : + static_cast(0); + } + + const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) { + const FieldDescriptor* field = GetFieldDescriptorOfType(type); + return field != NULL ? field->cpp_type_name() : ""; + } + + const Descriptor* GetMessageDescriptorForFieldType( + FieldDescriptor::Type type) { + const FieldDescriptor* field = GetFieldDescriptorOfType(type); + return field != NULL ? field->message_type() : NULL; + } + + const EnumDescriptor* GetEnumDescriptorForFieldType( + FieldDescriptor::Type type) { + const FieldDescriptor* field = GetFieldDescriptorOfType(type); + return field != NULL ? field->enum_type() : NULL; + } + + scoped_ptr pool_; }; +TEST_F(MiscTest, TypeNames) { + // Test that correct type names are returned. + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_STREQ("double" , GetTypeNameForFieldType(FD::TYPE_DOUBLE )); + EXPECT_STREQ("float" , GetTypeNameForFieldType(FD::TYPE_FLOAT )); + EXPECT_STREQ("int64" , GetTypeNameForFieldType(FD::TYPE_INT64 )); + EXPECT_STREQ("uint64" , GetTypeNameForFieldType(FD::TYPE_UINT64 )); + EXPECT_STREQ("int32" , GetTypeNameForFieldType(FD::TYPE_INT32 )); + EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 )); + EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 )); + EXPECT_STREQ("bool" , GetTypeNameForFieldType(FD::TYPE_BOOL )); + EXPECT_STREQ("string" , GetTypeNameForFieldType(FD::TYPE_STRING )); + EXPECT_STREQ("group" , GetTypeNameForFieldType(FD::TYPE_GROUP )); + EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE )); + EXPECT_STREQ("bytes" , GetTypeNameForFieldType(FD::TYPE_BYTES )); + EXPECT_STREQ("uint32" , GetTypeNameForFieldType(FD::TYPE_UINT32 )); + EXPECT_STREQ("enum" , GetTypeNameForFieldType(FD::TYPE_ENUM )); + EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32)); + EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64)); + EXPECT_STREQ("sint32" , GetTypeNameForFieldType(FD::TYPE_SINT32 )); + EXPECT_STREQ("sint64" , GetTypeNameForFieldType(FD::TYPE_SINT64 )); +} + +TEST_F(MiscTest, StaticTypeNames) { + // Test that correct type names are returned. + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_STREQ("double" , FD::TypeName(FD::TYPE_DOUBLE )); + EXPECT_STREQ("float" , FD::TypeName(FD::TYPE_FLOAT )); + EXPECT_STREQ("int64" , FD::TypeName(FD::TYPE_INT64 )); + EXPECT_STREQ("uint64" , FD::TypeName(FD::TYPE_UINT64 )); + EXPECT_STREQ("int32" , FD::TypeName(FD::TYPE_INT32 )); + EXPECT_STREQ("fixed64" , FD::TypeName(FD::TYPE_FIXED64 )); + EXPECT_STREQ("fixed32" , FD::TypeName(FD::TYPE_FIXED32 )); + EXPECT_STREQ("bool" , FD::TypeName(FD::TYPE_BOOL )); + EXPECT_STREQ("string" , FD::TypeName(FD::TYPE_STRING )); + EXPECT_STREQ("group" , FD::TypeName(FD::TYPE_GROUP )); + EXPECT_STREQ("message" , FD::TypeName(FD::TYPE_MESSAGE )); + EXPECT_STREQ("bytes" , FD::TypeName(FD::TYPE_BYTES )); + EXPECT_STREQ("uint32" , FD::TypeName(FD::TYPE_UINT32 )); + EXPECT_STREQ("enum" , FD::TypeName(FD::TYPE_ENUM )); + EXPECT_STREQ("sfixed32", FD::TypeName(FD::TYPE_SFIXED32)); + EXPECT_STREQ("sfixed64", FD::TypeName(FD::TYPE_SFIXED64)); + EXPECT_STREQ("sint32" , FD::TypeName(FD::TYPE_SINT32 )); + EXPECT_STREQ("sint64" , FD::TypeName(FD::TYPE_SINT64 )); +} + TEST_F(MiscTest, CppTypes) { // Test that CPP types are assigned correctly. @@ -1576,6 +1789,99 @@ TEST_F(MiscTest, CppTypes) { EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_SINT64 )); } +TEST_F(MiscTest, CppTypeNames) { + // Test that correct CPP type names are returned. + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_STREQ("double" , GetCppTypeNameForFieldType(FD::TYPE_DOUBLE )); + EXPECT_STREQ("float" , GetCppTypeNameForFieldType(FD::TYPE_FLOAT )); + EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_INT64 )); + EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_UINT64 )); + EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_INT32 )); + EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_FIXED64 )); + EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_FIXED32 )); + EXPECT_STREQ("bool" , GetCppTypeNameForFieldType(FD::TYPE_BOOL )); + EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_STRING )); + EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP )); + EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE )); + EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES )); + EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32 )); + EXPECT_STREQ("enum" , GetCppTypeNameForFieldType(FD::TYPE_ENUM )); + EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32)); + EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64)); + EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SINT32 )); + EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SINT64 )); +} + +TEST_F(MiscTest, StaticCppTypeNames) { + // Test that correct CPP type names are returned. + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_STREQ("int32" , FD::CppTypeName(FD::CPPTYPE_INT32 )); + EXPECT_STREQ("int64" , FD::CppTypeName(FD::CPPTYPE_INT64 )); + EXPECT_STREQ("uint32" , FD::CppTypeName(FD::CPPTYPE_UINT32 )); + EXPECT_STREQ("uint64" , FD::CppTypeName(FD::CPPTYPE_UINT64 )); + EXPECT_STREQ("double" , FD::CppTypeName(FD::CPPTYPE_DOUBLE )); + EXPECT_STREQ("float" , FD::CppTypeName(FD::CPPTYPE_FLOAT )); + EXPECT_STREQ("bool" , FD::CppTypeName(FD::CPPTYPE_BOOL )); + EXPECT_STREQ("enum" , FD::CppTypeName(FD::CPPTYPE_ENUM )); + EXPECT_STREQ("string" , FD::CppTypeName(FD::CPPTYPE_STRING )); + EXPECT_STREQ("message", FD::CppTypeName(FD::CPPTYPE_MESSAGE)); +} + +TEST_F(MiscTest, MessageType) { + // Test that message_type() is NULL for non-aggregate fields + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_DOUBLE )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FLOAT )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT64 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT64 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT32 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED64 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED32 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BOOL )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_STRING )); + EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_GROUP )); + EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_MESSAGE )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BYTES )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT32 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_ENUM )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED32)); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED64)); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT32 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT64 )); +} + +TEST_F(MiscTest, EnumType) { + // Test that enum_type() is NULL for non-enum fields + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_DOUBLE )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FLOAT )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT64 )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT64 )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT32 )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED64 )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED32 )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BOOL )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_STRING )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_GROUP )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_MESSAGE )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BYTES )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT32 )); + EXPECT_TRUE(NULL != GetEnumDescriptorForFieldType(FD::TYPE_ENUM )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED32)); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED64)); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT32 )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT64 )); +} + + TEST_F(MiscTest, DefaultValues) { // Test that setting default values works. FileDescriptorProto file_proto; @@ -1670,7 +1976,7 @@ TEST_F(MiscTest, DefaultValues) { message->field(3)->default_value_uint64()); EXPECT_EQ(4.5 , message->field(4)->default_value_float ()); EXPECT_EQ(10e100 , message->field(5)->default_value_double()); - EXPECT_EQ(true , message->field(6)->default_value_bool ()); + EXPECT_TRUE( message->field(6)->default_value_bool ()); EXPECT_EQ("hello" , message->field(7)->default_value_string()); EXPECT_EQ("\001\002\003" , message->field(8)->default_value_string()); EXPECT_EQ(enum_value_b , message->field(9)->default_value_enum ()); @@ -1693,7 +1999,7 @@ TEST_F(MiscTest, DefaultValues) { EXPECT_EQ(0 , message->field(14)->default_value_uint64()); EXPECT_EQ(0.0f , message->field(15)->default_value_float ()); EXPECT_EQ(0.0 , message->field(16)->default_value_double()); - EXPECT_EQ(false, message->field(17)->default_value_bool ()); + EXPECT_FALSE( message->field(17)->default_value_bool ()); EXPECT_EQ("" , message->field(18)->default_value_string()); EXPECT_EQ("" , message->field(19)->default_value_string()); EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum()); @@ -1739,13 +2045,31 @@ TEST_F(MiscTest, FieldOptions) { } // =================================================================== +enum DescriptorPoolMode { + NO_DATABASE, + FALLBACK_DATABASE +}; -class AllowUnknownDependenciesTest : public testing::Test { +class AllowUnknownDependenciesTest + : public testing::TestWithParam { protected: + DescriptorPoolMode mode() { + return GetParam(); + } + virtual void SetUp() { FileDescriptorProto foo_proto, bar_proto; - pool_.AllowUnknownDependencies(); + switch (mode()) { + case NO_DATABASE: + pool_.reset(new DescriptorPool); + break; + case FALLBACK_DATABASE: + pool_.reset(new DescriptorPool(&db_)); + break; + } + + pool_->AllowUnknownDependencies(); ASSERT_TRUE(TextFormat::ParseFromString( "name: 'foo.proto'" @@ -1776,13 +2100,13 @@ class AllowUnknownDependenciesTest : public testing::Test { &bar_proto)); // Collect pointers to stuff. - bar_file_ = pool_.BuildFile(bar_proto); + bar_file_ = BuildFile(bar_proto); ASSERT_TRUE(bar_file_ != NULL); ASSERT_EQ(1, bar_file_->message_type_count()); bar_type_ = bar_file_->message_type(0); - foo_file_ = pool_.BuildFile(foo_proto); + foo_file_ = BuildFile(foo_proto); ASSERT_TRUE(foo_file_ != NULL); ASSERT_EQ(1, foo_file_->message_type_count()); @@ -1794,6 +2118,20 @@ class AllowUnknownDependenciesTest : public testing::Test { qux_field_ = foo_type_->field(2); } + const FileDescriptor* BuildFile(const FileDescriptorProto& proto) { + switch (mode()) { + case NO_DATABASE: + return pool_->BuildFile(proto); + break; + case FALLBACK_DATABASE: { + EXPECT_TRUE(db_.Add(proto)); + return pool_->FindFileByName(proto.name()); + } + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; + } + const FileDescriptor* bar_file_; const Descriptor* bar_type_; const FileDescriptor* foo_file_; @@ -1802,46 +2140,50 @@ class AllowUnknownDependenciesTest : public testing::Test { const FieldDescriptor* baz_field_; const FieldDescriptor* qux_field_; - DescriptorPool pool_; + SimpleDescriptorDatabase db_; // used if in FALLBACK_DATABASE mode. + scoped_ptr pool_; }; -TEST_F(AllowUnknownDependenciesTest, PlaceholderFile) { +TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) { ASSERT_EQ(2, foo_file_->dependency_count()); EXPECT_EQ(bar_file_, foo_file_->dependency(0)); + EXPECT_FALSE(bar_file_->is_placeholder()); const FileDescriptor* baz_file = foo_file_->dependency(1); EXPECT_EQ("baz.proto", baz_file->name()); EXPECT_EQ(0, baz_file->message_type_count()); + EXPECT_TRUE(baz_file->is_placeholder()); // Placeholder files should not be findable. - EXPECT_EQ(bar_file_, pool_.FindFileByName(bar_file_->name())); - EXPECT_TRUE(pool_.FindFileByName(baz_file->name()) == NULL); + EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name())); + EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL); } -TEST_F(AllowUnknownDependenciesTest, PlaceholderTypes) { +TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) { ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type()); EXPECT_EQ(bar_type_, bar_field_->message_type()); + EXPECT_FALSE(bar_type_->is_placeholder()); ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type()); const Descriptor* baz_type = baz_field_->message_type(); EXPECT_EQ("Baz", baz_type->name()); EXPECT_EQ("Baz", baz_type->full_name()); - EXPECT_EQ("Baz.placeholder.proto", baz_type->file()->name()); EXPECT_EQ(0, baz_type->extension_range_count()); + EXPECT_TRUE(baz_type->is_placeholder()); ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type()); const EnumDescriptor* qux_type = qux_field_->enum_type(); EXPECT_EQ("Qux", qux_type->name()); EXPECT_EQ("corge.Qux", qux_type->full_name()); - EXPECT_EQ("corge.Qux.placeholder.proto", qux_type->file()->name()); + EXPECT_TRUE(qux_type->is_placeholder()); // Placeholder types should not be findable. - EXPECT_EQ(bar_type_, pool_.FindMessageTypeByName(bar_type_->full_name())); - EXPECT_TRUE(pool_.FindMessageTypeByName(baz_type->full_name()) == NULL); - EXPECT_TRUE(pool_.FindEnumTypeByName(qux_type->full_name()) == NULL); + EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name())); + EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL); + EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL); } -TEST_F(AllowUnknownDependenciesTest, CopyTo) { +TEST_P(AllowUnknownDependenciesTest, CopyTo) { // FieldDescriptor::CopyTo() should write non-fully-qualified type names // for placeholder types which were not originally fully-qualified. FieldDescriptorProto proto; @@ -1864,7 +2206,7 @@ TEST_F(AllowUnknownDependenciesTest, CopyTo) { EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type()); } -TEST_F(AllowUnknownDependenciesTest, CustomOptions) { +TEST_P(AllowUnknownDependenciesTest, CustomOptions) { // Qux should still have the uninterpreted option attached. ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size()); const UninterpretedOption& option = @@ -1873,7 +2215,7 @@ TEST_F(AllowUnknownDependenciesTest, CustomOptions) { EXPECT_EQ("grault", option.name(0).name_part()); } -TEST_F(AllowUnknownDependenciesTest, UnknownExtendee) { +TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) { // Test that we can extend an unknown type. This is slightly tricky because // it means that the placeholder type must have an extension range. @@ -1884,19 +2226,20 @@ TEST_F(AllowUnknownDependenciesTest, UnknownExtendee) { "extension { extendee: 'UnknownType' name:'some_extension' number:123" " label:LABEL_OPTIONAL type:TYPE_INT32 }", &extension_proto)); - const FileDescriptor* file = pool_.BuildFile(extension_proto); + const FileDescriptor* file = BuildFile(extension_proto); ASSERT_TRUE(file != NULL); ASSERT_EQ(1, file->extension_count()); const Descriptor* extendee = file->extension(0)->containing_type(); EXPECT_EQ("UnknownType", extendee->name()); + EXPECT_TRUE(extendee->is_placeholder()); ASSERT_EQ(1, extendee->extension_range_count()); EXPECT_EQ(1, extendee->extension_range(0)->start); EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end); } -TEST_F(AllowUnknownDependenciesTest, CustomOption) { +TEST_P(AllowUnknownDependenciesTest, CustomOption) { // Test that we can use a custom option without having parsed // descriptor.proto. @@ -1937,7 +2280,7 @@ TEST_F(AllowUnknownDependenciesTest, CustomOption) { "}", &option_proto)); - const FileDescriptor* file = pool_.BuildFile(option_proto); + const FileDescriptor* file = BuildFile(option_proto); ASSERT_TRUE(file != NULL); // Verify that no extension options were set, but they were left as @@ -1949,6 +2292,81 @@ TEST_F(AllowUnknownDependenciesTest, CustomOption) { EXPECT_EQ(2, file->options().uninterpreted_option_size()); } +TEST_P(AllowUnknownDependenciesTest, + UndeclaredDependencyTriggersBuildOfDependency) { + // Crazy case: suppose foo.proto refers to a symbol without declaring the + // dependency that finds it. In the event that the pool is backed by a + // DescriptorDatabase, the pool will attempt to find the symbol in the + // database. If successful, it will build the undeclared dependency to verify + // that the file does indeed contain the symbol. If that file fails to build, + // then its descriptors must be rolled back. However, we still want foo.proto + // to build successfully, since we are allowing unknown dependencies. + + FileDescriptorProto undeclared_dep_proto; + // We make this file fail to build by giving it two fields with tag 1. + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"invalid_file_as_undeclared_dep.proto\" " + "package: \"undeclared\" " + "message_type: { " + " name: \"Quux\" " + " field { " + " name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 " + " }" + " field { " + " name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 " + " }" + "}", + &undeclared_dep_proto)); + // We can't use the BuildFile() helper because we don't actually want to build + // it into the descriptor pool in the fallback database case: it just needs to + // be sitting in the database so that it gets built during the building of + // test.proto below. + switch (mode()) { + case NO_DATABASE: { + ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == NULL); + break; + } + case FALLBACK_DATABASE: { + ASSERT_TRUE(db_.Add(undeclared_dep_proto)); + } + } + + FileDescriptorProto test_proto; + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"test.proto\" " + "message_type: { " + " name: \"Corge\" " + " field { " + " name:'quux' number:1 label: LABEL_OPTIONAL " + " type_name:'undeclared.Quux' type: TYPE_MESSAGE " + " }" + "}", + &test_proto)); + + const FileDescriptor* file = BuildFile(test_proto); + ASSERT_TRUE(file != NULL); + GOOGLE_LOG(INFO) << file->DebugString(); + + EXPECT_EQ(0, file->dependency_count()); + ASSERT_EQ(1, file->message_type_count()); + const Descriptor* corge_desc = file->message_type(0); + ASSERT_EQ("Corge", corge_desc->name()); + ASSERT_EQ(1, corge_desc->field_count()); + EXPECT_FALSE(corge_desc->is_placeholder()); + + const FieldDescriptor* quux_field = corge_desc->field(0); + ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type()); + ASSERT_EQ("Quux", quux_field->message_type()->name()); + ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name()); + EXPECT_TRUE(quux_field->message_type()->is_placeholder()); + // The place holder type should not be findable. + ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL); +} + +INSTANTIATE_TEST_CASE_P(DatabaseSource, + AllowUnknownDependenciesTest, + testing::Values(NO_DATABASE, FALLBACK_DATABASE)); + // =================================================================== TEST(CustomOptions, OptionLocations) { @@ -2212,6 +2630,230 @@ TEST(CustomOptions, MessageOptionThreeFieldsSet) { EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo()); } +TEST(CustomOptions, MessageOptionRepeatedLeafFieldSet) { + // This test verifies that repeated fields in custom options can be + // given multiple values by repeating the option with a different value. + // This test checks repeated leaf values. Each repeated custom value + // appears in a different uninterpreted_option, which will be concatenated + // when they are merged into the final option value. + DescriptorPool pool; + + FileDescriptorProto file_proto; + FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + protobuf_unittest::TestMessageWithCustomOptions::descriptor() + ->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + // The following represents the definition: + // + // import "google/protobuf/unittest_custom_options.proto" + // package protobuf_unittest; + // message Foo { + // option (complex_opt1).foo4 = 12; + // option (complex_opt1).foo4 = 34; + // option (complex_opt1).foo4 = 56; + // } + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" " + "message_type { " + " name: \"Foo\" " + " options { " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo4\" " + " is_extension: false " + " } " + " positive_int_value: 12 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo4\" " + " is_extension: false " + " } " + " positive_int_value: 34 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo4\" " + " is_extension: false " + " } " + " positive_int_value: 56 " + " } " + " } " + "}", + &file_proto)); + + const FileDescriptor* file = pool.BuildFile(file_proto); + ASSERT_TRUE(file != NULL); + ASSERT_EQ(1, file->message_type_count()); + + const MessageOptions& options = file->message_type(0)->options(); + EXPECT_EQ(3, options.GetExtension(protobuf_unittest::complex_opt1).foo4_size()); + EXPECT_EQ(12, options.GetExtension(protobuf_unittest::complex_opt1).foo4(0)); + EXPECT_EQ(34, options.GetExtension(protobuf_unittest::complex_opt1).foo4(1)); + EXPECT_EQ(56, options.GetExtension(protobuf_unittest::complex_opt1).foo4(2)); +} + +TEST(CustomOptions, MessageOptionRepeatedMsgFieldSet) { + // This test verifies that repeated fields in custom options can be + // given multiple values by repeating the option with a different value. + // This test checks repeated message values. Each repeated custom value + // appears in a different uninterpreted_option, which will be concatenated + // when they are merged into the final option value. + DescriptorPool pool; + + FileDescriptorProto file_proto; + FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + protobuf_unittest::TestMessageWithCustomOptions::descriptor() + ->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + // The following represents the definition: + // + // import "google/protobuf/unittest_custom_options.proto" + // package protobuf_unittest; + // message Foo { + // option (complex_opt2).barney = {waldo: 1}; + // option (complex_opt2).barney = {waldo: 10}; + // option (complex_opt2).barney = {waldo: 100}; + // } + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" " + "message_type { " + " name: \"Foo\" " + " options { " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt2\" " + " is_extension: true " + " } " + " name { " + " name_part: \"barney\" " + " is_extension: false " + " } " + " aggregate_value: \"waldo: 1\" " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt2\" " + " is_extension: true " + " } " + " name { " + " name_part: \"barney\" " + " is_extension: false " + " } " + " aggregate_value: \"waldo: 10\" " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt2\" " + " is_extension: true " + " } " + " name { " + " name_part: \"barney\" " + " is_extension: false " + " } " + " aggregate_value: \"waldo: 100\" " + " } " + " } " + "}", + &file_proto)); + + const FileDescriptor* file = pool.BuildFile(file_proto); + ASSERT_TRUE(file != NULL); + ASSERT_EQ(1, file->message_type_count()); + + const MessageOptions& options = file->message_type(0)->options(); + EXPECT_EQ(3, options.GetExtension( + protobuf_unittest::complex_opt2).barney_size()); + EXPECT_EQ(1,options.GetExtension( + protobuf_unittest::complex_opt2).barney(0).waldo()); + EXPECT_EQ(10, options.GetExtension( + protobuf_unittest::complex_opt2).barney(1).waldo()); + EXPECT_EQ(100, options.GetExtension( + protobuf_unittest::complex_opt2).barney(2).waldo()); +} + +// Check that aggregate options were parsed and saved correctly in +// the appropriate descriptors. +TEST(CustomOptions, AggregateOptions) { + const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor(); + const FileDescriptor* file = msg->file(); + const FieldDescriptor* field = msg->FindFieldByName("fieldname"); + const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum"); + const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE"); + const ServiceDescriptor* service = file->FindServiceByName( + "AggregateService"); + const MethodDescriptor* method = service->FindMethodByName("Method"); + + // Tests for the different types of data embedded in fileopt + const protobuf_unittest::Aggregate& file_options = + file->options().GetExtension(protobuf_unittest::fileopt); + EXPECT_EQ(100, file_options.i()); + EXPECT_EQ("FileAnnotation", file_options.s()); + EXPECT_EQ("NestedFileAnnotation", file_options.sub().s()); + EXPECT_EQ("FileExtensionAnnotation", + file_options.file().GetExtension(protobuf_unittest::fileopt).s()); + EXPECT_EQ("EmbeddedMessageSetElement", + file_options.mset().GetExtension( + protobuf_unittest::AggregateMessageSetElement + ::message_set_extension).s()); + + // Simple tests for all the other types of annotations + EXPECT_EQ("MessageAnnotation", + msg->options().GetExtension(protobuf_unittest::msgopt).s()); + EXPECT_EQ("FieldAnnotation", + field->options().GetExtension(protobuf_unittest::fieldopt).s()); + EXPECT_EQ("EnumAnnotation", + enumd->options().GetExtension(protobuf_unittest::enumopt).s()); + EXPECT_EQ("EnumValueAnnotation", + enumv->options().GetExtension(protobuf_unittest::enumvalopt).s()); + EXPECT_EQ("ServiceAnnotation", + service->options().GetExtension(protobuf_unittest::serviceopt).s()); + EXPECT_EQ("MethodAnnotation", + method->options().GetExtension(protobuf_unittest::methodopt).s()); +} + +TEST(CustomOptions, UnusedImportWarning) { + DescriptorPool pool; + + FileDescriptorProto file_proto; + FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + protobuf_unittest::TestMessageWithCustomOptions::descriptor() + ->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + + pool.AddUnusedImportTrackFile("custom_options_import.proto"); + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" ", + &file_proto)); + pool.BuildFile(file_proto); +} // =================================================================== @@ -2226,6 +2868,7 @@ class MockErrorCollector : public DescriptorPool::ErrorCollector { ~MockErrorCollector() {} string text_; + string warning_text_; // implements ErrorCollector --------------------------------------- void AddError(const string& filename, @@ -2249,9 +2892,32 @@ class MockErrorCollector : public DescriptorPool::ErrorCollector { &text_, "$0: $1: $2: $3\n", filename, element_name, location_name, message); } -}; -class ValidationErrorTest : public testing::Test { + // implements ErrorCollector --------------------------------------- + void AddWarning(const string& filename, const string& element_name, + const Message* descriptor, ErrorLocation location, + const string& message) { + const char* location_name = NULL; + switch (location) { + case NAME : location_name = "NAME" ; break; + case NUMBER : location_name = "NUMBER" ; break; + case TYPE : location_name = "TYPE" ; break; + case EXTENDEE : location_name = "EXTENDEE" ; break; + case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break; + case OPTION_NAME : location_name = "OPTION_NAME" ; break; + case OPTION_VALUE : location_name = "OPTION_VALUE" ; break; + case INPUT_TYPE : location_name = "INPUT_TYPE" ; break; + case OUTPUT_TYPE : location_name = "OUTPUT_TYPE" ; break; + case OTHER : location_name = "OTHER" ; break; + } + + strings::SubstituteAndAppend( + &warning_text_, "$0: $1: $2: $3\n", + filename, element_name, location_name, message); + } +}; + +class ValidationErrorTest : public testing::Test { protected: // Parse file_text as a FileDescriptorProto in text format and add it // to the DescriptorPool. Expect no errors. @@ -2275,6 +2941,19 @@ class ValidationErrorTest : public testing::Test { EXPECT_EQ(expected_errors, error_collector.text_); } + // Parse file_text as a FileDescriptorProto in text format and add it + // to the DescriptorPool. Expect errors to be produced which match the + // given warning text. + void BuildFileWithWarnings(const string& file_text, + const string& expected_warnings) { + FileDescriptorProto file_proto; + ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); + + MockErrorCollector error_collector; + EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector)); + EXPECT_EQ(expected_warnings, error_collector.warning_text_); + } + // Builds some already-parsed file in our test pool. void BuildFileInTestPool(const FileDescriptor* file) { FileDescriptorProto file_proto; @@ -2412,6 +3091,15 @@ TEST_F(ValidationErrorTest, UnknownDependency) { "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n"); } +TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) { + BuildFile("name: \"foo.proto\""); + BuildFileWithErrors( + "name: \"bar.proto\" " + "dependency: \"foo.proto\" " + "public_dependency: 1", + "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n"); +} + TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) { // Used to crash: If we depend on a non-existent file and then refer to a // package defined in a file that we didn't import, and that package is @@ -2519,8 +3207,8 @@ TEST_F(ValidationErrorTest, InvalidDefaults) { " default_value: \"1\" }" "}", - "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value.\n" - "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value.\n" + "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value \"abc\".\n" + "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value \"\".\n" "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or " "false.\n" "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n" @@ -2603,6 +3291,38 @@ TEST_F(ValidationErrorTest, NonExtensionWithExtendee) { "non-extension field.\n"); } +TEST_F(ValidationErrorTest, FieldOneofIndexTooLarge) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 1 }" + " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 0 }" + " oneof_decl { name:\"bar\" }" + "}", + + "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index 1 is out of " + "range for type \"Foo\".\n"); +} + +TEST_F(ValidationErrorTest, FieldOneofIndexNegative) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: -1 }" + " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 0 }" + " oneof_decl { name:\"bar\" }" + "}", + + "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index -1 is out of " + "range for type \"Foo\".\n"); +} + TEST_F(ValidationErrorTest, FieldNumberConflict) { BuildFileWithErrors( "name: \"foo.proto\" " @@ -2763,6 +3483,28 @@ TEST_F(ValidationErrorTest, NotAnExtensionNumber) { "number.\n"); } +TEST_F(ValidationErrorTest, RequiredExtension) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + " extension_range { start: 1000 end: 10000 }" + "}" + "message_type {" + " name: \"Foo\"" + " extension {" + " name:\"foo\"" + " number:1000" + " label:LABEL_REQUIRED" + " type:TYPE_INT32" + " extendee: \"Bar\"" + " }" + "}", + + "foo.proto: Foo.foo: TYPE: Message extensions cannot have required " + "fields.\n"); +} + TEST_F(ValidationErrorTest, UndefinedFieldType) { BuildFileWithErrors( "name: \"foo.proto\" " @@ -2774,6 +3516,36 @@ TEST_F(ValidationErrorTest, UndefinedFieldType) { "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n"); } +TEST_F(ValidationErrorTest, UndefinedFieldTypeWithDefault) { + // See b/12533582. Previously this failed because the default value was not + // accepted by the parser, which assumed an enum type, leading to an unclear + // error message. We want this input to yield a validation error instead, + // since the unknown type is the primary problem. + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"int\" " + " default_value:\"1\" }" + "}", + + "foo.proto: Foo.foo: TYPE: \"int\" is not defined.\n"); +} + +TEST_F(ValidationErrorTest, UndefinedNestedFieldType) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " nested_type { name:\"Baz\" }" + " field { name:\"foo\" number:1" + " label:LABEL_OPTIONAL" + " type_name:\"Foo.Baz.Bar\" }" + "}", + + "foo.proto: Foo.foo: TYPE: \"Foo.Baz.Bar\" is not defined.\n"); +} + TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) { BuildFile( "name: \"bar.proto\" " @@ -2790,8 +3562,167 @@ TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) { "necessary import.\n"); } +TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) { + // Test for hidden dependencies. + // + // // bar.proto + // message Bar{} + // + // // forward.proto + // import "bar.proto" + // + // // foo.proto + // import "forward.proto" + // message Foo { + // optional Bar foo = 1; // Error, needs to import bar.proto explicitly. + // } + // + BuildFile( + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); + + BuildFile( + "name: \"forward.proto\"" + "dependency: \"bar.proto\""); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"forward.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}", + "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " + "which is not imported by \"foo.proto\". To use it here, please add the " + "necessary import.\n"); +} + +TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) { + // Test for public dependencies. + // + // // bar.proto + // message Bar{} + // + // // forward.proto + // import public "bar.proto" + // + // // foo.proto + // import "forward.proto" + // message Foo { + // optional Bar foo = 1; // Correct. "bar.proto" is public imported into + // // forward.proto, so when "foo.proto" imports + // // "forward.proto", it imports "bar.proto" too. + // } + // + BuildFile( + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); + + BuildFile( + "name: \"forward.proto\"" + "dependency: \"bar.proto\" " + "public_dependency: 0"); + + BuildFile( + "name: \"foo.proto\" " + "dependency: \"forward.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}"); +} + +TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) { + // Test for public dependencies. + // + // // bar.proto + // message Bar{} + // + // // forward.proto + // import public "bar.proto" + // + // // forward2.proto + // import public "forward.proto" + // + // // foo.proto + // import "forward2.proto" + // message Foo { + // optional Bar foo = 1; // Correct, public imports are transitive. + // } + // + BuildFile( + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); + + BuildFile( + "name: \"forward.proto\"" + "dependency: \"bar.proto\" " + "public_dependency: 0"); + + BuildFile( + "name: \"forward2.proto\"" + "dependency: \"forward.proto\" " + "public_dependency: 0"); + + BuildFile( + "name: \"foo.proto\" " + "dependency: \"forward2.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}"); +} + +TEST_F(ValidationErrorTest, + FieldTypeDefinedInPrivateDependencyOfPublicDependency) { + // Test for public dependencies. + // + // // bar.proto + // message Bar{} + // + // // forward.proto + // import "bar.proto" + // + // // forward2.proto + // import public "forward.proto" + // + // // foo.proto + // import "forward2.proto" + // message Foo { + // optional Bar foo = 1; // Error, the "bar.proto" is not public imported + // // into "forward.proto", so will not be imported + // // into either "forward2.proto" or "foo.proto". + // } + // + BuildFile( + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); + + BuildFile( + "name: \"forward.proto\"" + "dependency: \"bar.proto\""); + + BuildFile( + "name: \"forward2.proto\"" + "dependency: \"forward.proto\" " + "public_dependency: 0"); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"forward2.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}", + "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " + "which is not imported by \"foo.proto\". To use it here, please add the " + "necessary import.\n"); +} + + TEST_F(ValidationErrorTest, SearchMostLocalFirst) { - // The following should produce an error that Bar.Baz is not defined: + // The following should produce an error that Bar.Baz is resolved but + // not defined: // message Bar { message Baz {} } // message Foo { // message Bar { @@ -2817,7 +3748,10 @@ TEST_F(ValidationErrorTest, SearchMostLocalFirst) { " type_name:\"Bar.Baz\" }" "}", - "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is not defined.\n"); + "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is resolved to \"Foo.Bar.Baz\"," + " which is not defined. The innermost scope is searched first in name " + "resolution. Consider using a leading '.'(i.e., \".Bar.Baz\") to start " + "from the outermost scope.\n"); } TEST_F(ValidationErrorTest, SearchMostLocalFirst2) { @@ -2959,6 +3893,20 @@ TEST_F(ValidationErrorTest, BadEnumDefaultValue) { "\"NO_SUCH_VALUE\".\n"); } +TEST_F(ValidationErrorTest, EnumDefaultValueIsInteger) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\"" + " default_value:\"0\" }" + "}", + + "foo.proto: Foo.foo: DEFAULT_VALUE: Default value for an enum field must " + "be an identifier.\n"); +} + TEST_F(ValidationErrorTest, PrimitiveWithTypeName) { BuildFileWithErrors( "name: \"foo.proto\" " @@ -2983,6 +3931,31 @@ TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) { "type_name.\n"); } +TEST_F(ValidationErrorTest, OneofWithNoFields) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " oneof_decl { name:\"bar\" }" + "}", + + "foo.proto: Foo.bar: NAME: Oneof must have at least one field.\n"); +} + +TEST_F(ValidationErrorTest, OneofLabelMismatch) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_REPEATED type:TYPE_INT32 " + " oneof_index:0 }" + " oneof_decl { name:\"bar\" }" + "}", + + "foo.proto: Foo.foo: NAME: Fields of oneofs must themselves have label " + "LABEL_OPTIONAL.\n"); +} + TEST_F(ValidationErrorTest, InputTypeNotDefined) { BuildFileWithErrors( "name: \"foo.proto\" " @@ -2992,7 +3965,8 @@ TEST_F(ValidationErrorTest, InputTypeNotDefined) { " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }" "}", - "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n"); + "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n" + ); } TEST_F(ValidationErrorTest, InputTypeNotAMessage) { @@ -3005,7 +3979,8 @@ TEST_F(ValidationErrorTest, InputTypeNotAMessage) { " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }" "}", - "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n"); + "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n" + ); } TEST_F(ValidationErrorTest, OutputTypeNotDefined) { @@ -3017,7 +3992,8 @@ TEST_F(ValidationErrorTest, OutputTypeNotDefined) { " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }" "}", - "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n"); + "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n" + ); } TEST_F(ValidationErrorTest, OutputTypeNotAMessage) { @@ -3030,9 +4006,11 @@ TEST_F(ValidationErrorTest, OutputTypeNotAMessage) { " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }" "}", - "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n"); + "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n" + ); } + TEST_F(ValidationErrorTest, IllegalPackedField) { BuildFileWithErrors( "name: \"foo.proto\" " @@ -3139,20 +4117,85 @@ TEST_F(ValidationErrorTest, InvalidOptionName) { "reserved name \"uninterpreted_option\".\n"); } -TEST_F(ValidationErrorTest, RepeatedOption) { +TEST_F(ValidationErrorTest, RepeatedMessageOption) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( "name: \"foo.proto\" " "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_REPEATED " - " type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " + "message_type: { name: \"Bar\" field: { " + " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } " + "} " + "extension { name: \"bar\" number: 7672757 label: LABEL_REPEATED " + " type: TYPE_MESSAGE type_name: \"Bar\" " + " extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"bar\" " + " is_extension: true } " + " name { name_part: \"foo\" " + " is_extension: false } " + " positive_int_value: 1 } }", + + "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" is a " + "repeated message. Repeated message options must be initialized " + "using an aggregate value.\n"); +} + +TEST_F(ValidationErrorTest, ResolveUndefinedOption) { + // The following should produce an eror that baz.bar is resolved but not + // defined. + // foo.proto: + // package baz + // import google/protobuf/descriptor.proto + // message Bar { optional int32 foo = 1; } + // extend FileOptions { optional Bar bar = 7672757; } + // + // qux.proto: + // package qux.baz + // option (baz.bar).foo = 1; + // + // Although "baz.bar" is already defined, the lookup code will try + // "qux.baz.bar", since it's the match from the innermost scope, which will + // cause a symbol not defined error. + BuildDescriptorMessagesInTestPool(); + + BuildFile( + "name: \"foo.proto\" " + "package: \"baz\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "message_type: { name: \"Bar\" field: { " + " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } " + "} " + "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_MESSAGE type_name: \"Bar\" " + " extendee: \"google.protobuf.FileOptions\" }"); + + BuildFileWithErrors( + "name: \"qux.proto\" " + "package: \"qux.baz\" " + "options { uninterpreted_option { name { name_part: \"baz.bar\" " + " is_extension: true } " + " name { name_part: \"foo\" " + " is_extension: false } " + " positive_int_value: 1 } }", + + "qux.proto: qux.proto: OPTION_NAME: Option \"(baz.bar)\" is resolved to " + "\"(qux.baz.bar)\"," + " which is not defined. The innermost scope is searched first in name " + "resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\") to start " + "from the outermost scope.\n"); +} + +TEST_F(ValidationErrorTest, UnknownOption) { + BuildFileWithErrors( + "name: \"qux.proto\" " + "package: \"qux.baz\" " + "options { uninterpreted_option { name { name_part: \"baaz.bar\" " " is_extension: true } " - " double_value: 1.2 } }", + " name { name_part: \"foo\" " + " is_extension: false } " + " positive_int_value: 1 } }", - "foo.proto: foo.proto: OPTION_NAME: Option field \"(foo)\" is repeated. " - "Repeated options are not supported.\n"); + "qux.proto: qux.proto: OPTION_NAME: Option \"(baaz.bar)\" unknown.\n"); } TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) { @@ -3425,25 +4468,69 @@ TEST_F(ValidationErrorTest, StringOptionValueIsNotString) { "string option \"foo\".\n"); } -TEST_F(ValidationErrorTest, TryingToSetMessageValuedOption) { +TEST_F(ValidationErrorTest, DuplicateExtensionFieldNumber) { + BuildDescriptorMessagesInTestPool(); + + BuildFile( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"option1\" number: 1000 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"); + + BuildFileWithWarnings( + "name: \"bar.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"option2\" number: 1000 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }", + "bar.proto: option2: NUMBER: Extension number 1000 has already been used " + "in \"google.protobuf.FileOptions\" by extension \"option1\" defined in " + "foo.proto.\n"); +} + +// Helper function for tests that check for aggregate value parsing +// errors. The "value" argument is embedded inside the +// "uninterpreted_option" portion of the result. +static string EmbedAggregateValue(const char* value) { + return strings::Substitute( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "message_type { name: \"Foo\" } " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_MESSAGE type_name: \"Foo\" " + " extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " $0 } }", + value); +} + +TEST_F(ValidationErrorTest, AggregateValueNotFound) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "message_type { " - " name: \"TestMessage\" " - " field { name:\"baz\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING }" - "}" - "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_MESSAGE type_name: \"TestMessage\" " - " extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"bar\" " - " is_extension: true } " - " identifier_value: \"QUUX\" } }", + EmbedAggregateValue("string_value: \"\""), + "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. " + "To set the entire message, use syntax like " + "\"foo = { }\". To set fields within it, use " + "syntax like \"foo.foo = value\".\n"); +} + +TEST_F(ValidationErrorTest, AggregateValueParseError) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + EmbedAggregateValue("aggregate_value: \"1+2\""), + "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option " + "value for \"foo\": Expected identifier.\n"); +} + +TEST_F(ValidationErrorTest, AggregateValueUnknownFields) { + BuildDescriptorMessagesInTestPool(); - "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" cannot be of " - "message type.\n"); + BuildFileWithErrors( + EmbedAggregateValue("aggregate_value: \"x:100\""), + "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option " + "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n"); } TEST_F(ValidationErrorTest, NotLiteImportsLite) { @@ -3483,11 +4570,25 @@ TEST_F(ValidationErrorTest, LiteExtendsNotLite) { TEST_F(ValidationErrorTest, NoLiteServices) { BuildFileWithErrors( "name: \"foo.proto\" " - "options { optimize_for: LITE_RUNTIME } " + "options {" + " optimize_for: LITE_RUNTIME" + " cc_generic_services: true" + " java_generic_services: true" + "} " "service { name: \"Foo\" }", "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot " - "define services.\n"); + "define services unless you set both options cc_generic_services and " + "java_generic_sevices to false.\n"); + + BuildFile( + "name: \"bar.proto\" " + "options {" + " optimize_for: LITE_RUNTIME" + " cc_generic_services: false" + " java_generic_services: false" + "} " + "service { name: \"Bar\" }"); } TEST_F(ValidationErrorTest, RollbackAfterError) { @@ -3514,7 +4615,8 @@ TEST_F(ValidationErrorTest, RollbackAfterError) { " }" "}", - "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n"); + "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n" + ); // Make sure that if we build the same file again with the error fixed, // it works. If the above rollback was incomplete, then some symbols will @@ -3563,6 +4665,78 @@ TEST_F(ValidationErrorTest, ErrorsReportedToLogError) { EXPECT_EQ(" Foo: \"Foo\" is already defined.", errors[1]); } +TEST_F(ValidationErrorTest, DisallowEnumAlias) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Bar\"" + " value { name:\"ENUM_A\" number:0 }" + " value { name:\"ENUM_B\" number:0 }" + "}", + "foo.proto: Bar: NUMBER: " + "\"ENUM_B\" uses the same enum value as \"ENUM_A\". " + "If this is intended, set 'option allow_alias = true;' to the enum " + "definition.\n"); +} + +TEST_F(ValidationErrorTest, AllowEnumAlias) { + BuildFile( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Bar\"" + " value { name:\"ENUM_A\" number:0 }" + " value { name:\"ENUM_B\" number:0 }" + " options { allow_alias: true }" + "}"); +} + +TEST_F(ValidationErrorTest, UnusedImportWarning) { + + pool_.AddUnusedImportTrackFile("bar.proto"); + BuildFile( + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); + + pool_.AddUnusedImportTrackFile("base.proto"); + BuildFile( + "name: \"base.proto\" " + "message_type { name: \"Base\" }"); + + pool_.AddUnusedImportTrackFile("baz.proto"); + BuildFile( + "name: \"baz.proto\" " + "message_type { name: \"Baz\" }"); + + pool_.AddUnusedImportTrackFile("public.proto"); + BuildFile( + "name: \"public.proto\" " + "dependency: \"bar.proto\"" + "public_dependency: 0"); + + // // forward.proto + // import "base.proto" // No warning: Base message is used. + // import "bar.proto" // Will log a warning. + // import public "baz.proto" // No warning: Do not track import public. + // import "public.proto" // No warning: public.proto has import public. + // message Forward { + // optional Base base = 1; + // } + // + pool_.AddUnusedImportTrackFile("forward.proto"); + BuildFile( + "name: \"forward.proto\"" + "dependency: \"base.proto\"" + "dependency: \"bar.proto\"" + "dependency: \"baz.proto\"" + "dependency: \"public.proto\"" + "public_dependency: 2 " + "message_type {" + " name: \"Forward\"" + " field { name:\"base\" number:1 label:LABEL_OPTIONAL type_name:\"Base\" }" + "}"); +} + + // =================================================================== // DescriptorDatabase @@ -3581,16 +4755,23 @@ class DatabaseBackedPoolTest : public testing::Test { virtual void SetUp() { AddToDatabase(&database_, - "name: \"foo.proto\" " - "message_type { name:\"Foo\" extension_range { start: 1 end: 100 } } " - "enum_type { name:\"TestEnum\" value { name:\"DUMMY\" number:0 } } " - "service { name:\"TestService\" } "); + "name: 'foo.proto' " + "message_type { name:'Foo' extension_range { start: 1 end: 100 } } " + "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } " + "service { name:'TestService' } "); AddToDatabase(&database_, - "name: \"bar.proto\" " - "dependency: \"foo.proto\" " - "message_type { name:\"Bar\" } " - "extension { name:\"foo_ext\" extendee: \".Foo\" number:5 " + "name: 'bar.proto' " + "dependency: 'foo.proto' " + "message_type { name:'Bar' } " + "extension { name:'foo_ext' extendee: '.Foo' number:5 " " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + // Baz has an undeclared dependency on Foo. + AddToDatabase(&database_, + "name: 'baz.proto' " + "message_type { " + " name:'Baz' " + " field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } " + "}"); } // We can't inject a file containing errors into a DescriptorPool, so we @@ -3829,6 +5010,33 @@ TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) { error_collector.text_); } +TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) { + // Check that we find and report undeclared dependencies on types that exist + // in the descriptor database but that have not not been built yet. + MockErrorCollector error_collector; + DescriptorPool pool(&database_, &error_collector); + EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL); + EXPECT_EQ( + "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", " + "which is not imported by \"baz.proto\". To use it here, please add " + "the necessary import.\n", + error_collector.text_); +} + +TEST_F(DatabaseBackedPoolTest, RollbackAfterError) { + // Make sure that all traces of bad types are removed from the pool. This used + // to be b/4529436, due to the fact that a symbol resolution failure could + // potentially cause another file to be recursively built, which would trigger + // a checkpoint _past_ possibly invalid symbols. + // Baz is defined in the database, but the file is invalid because it is + // missing a necessary import. + DescriptorPool pool(&database_); + EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL); + // Make sure that searching again for the file or the type fails. + EXPECT_TRUE(pool.FindFileByName("baz.proto") == NULL); + EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL); +} + TEST_F(DatabaseBackedPoolTest, UnittestProto) { // Try to load all of unittest.proto from a DescriptorDatabase. This should // thoroughly test all paths through DescriptorBuilder to insure that there @@ -3851,6 +5059,10 @@ TEST_F(DatabaseBackedPoolTest, UnittestProto) { EXPECT_EQ(original_file_proto.DebugString(), file_from_database_proto.DebugString()); + + // Also verify that CopyTo() did not omit any information. + EXPECT_EQ(original_file->DebugString(), + file_from_database->DebugString()); } TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) { @@ -3885,6 +5097,16 @@ TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) { EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL); EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL); EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL); + + EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == NULL); + EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == NULL); + EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == NULL); + EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == NULL); + EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == NULL); + EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == NULL); + EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == NULL); + EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == NULL); + EXPECT_EQ(0, call_counter.call_count_); } @@ -3909,15 +5131,93 @@ TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) { EXPECT_EQ("", error_collector.text_); } +// DescriptorDatabase that attempts to induce exponentially-bad performance +// in DescriptorPool. For every positive N, the database contains a file +// fileN.proto, which defines a message MessageN, which contains fields of +// type MessageK for all K in [0,N). Message0 is not defined anywhere +// (file0.proto exists, but is empty), so every other file and message type +// will fail to build. +// +// If the DescriptorPool is not careful to memoize errors, an attempt to +// build a descriptor for MessageN can require O(2^N) time. +class ExponentialErrorDatabase : public DescriptorDatabase { + public: + ExponentialErrorDatabase() {} + ~ExponentialErrorDatabase() {} + + // implements DescriptorDatabase --------------------------------- + bool FindFileByName(const string& filename, + FileDescriptorProto* output) { + int file_num = -1; + FullMatch(filename, "file", ".proto", &file_num); + if (file_num > -1) { + return PopulateFile(file_num, output); + } else { + return false; + } + } + bool FindFileContainingSymbol(const string& symbol_name, + FileDescriptorProto* output) { + int file_num = -1; + FullMatch(symbol_name, "Message", "", &file_num); + if (file_num > 0) { + return PopulateFile(file_num, output); + } else { + return false; + } + } + bool FindFileContainingExtension(const string& containing_type, + int field_number, + FileDescriptorProto* output) { + return false; + } + + private: + void FullMatch(const string& name, + const string& begin_with, + const string& end_with, + int* file_num) { + int begin_size = begin_with.size(); + int end_size = end_with.size(); + if (name.substr(0, begin_size) != begin_with || + name.substr(name.size()- end_size, end_size) != end_with) { + return; + } + safe_strto32(name.substr(begin_size, name.size() - end_size - begin_size), + file_num); + } + + bool PopulateFile(int file_num, FileDescriptorProto* output) { + using strings::Substitute; + GOOGLE_CHECK_GE(file_num, 0); + output->Clear(); + output->set_name(Substitute("file$0.proto", file_num)); + // file0.proto doesn't define Message0 + if (file_num > 0) { + DescriptorProto* message = output->add_message_type(); + message->set_name(Substitute("Message$0", file_num)); + for (int i = 0; i < file_num; ++i) { + output->add_dependency(Substitute("file$0.proto", i)); + FieldDescriptorProto* field = message->add_field(); + field->set_name(Substitute("field$0", i)); + field->set_number(i); + field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); + field->set_type(FieldDescriptorProto::TYPE_MESSAGE); + field->set_type_name(Substitute("Message$0", i)); + } + } + return true; + } +}; + TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) { - ErrorDescriptorDatabase error_database; - MockErrorCollector error_collector; - DescriptorPool pool(&error_database, &error_collector); + ExponentialErrorDatabase error_database; + DescriptorPool pool(&error_database); - EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL); - error_collector.text_.clear(); - EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL); - EXPECT_EQ("", error_collector.text_); + GOOGLE_LOG(INFO) << "A timeout in this test probably indicates a real bug."; + + EXPECT_TRUE(pool.FindFileByName("file40.proto") == NULL); + EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == NULL); } TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) { @@ -3950,6 +5250,251 @@ TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) { // =================================================================== +class AbortingErrorCollector : public DescriptorPool::ErrorCollector { + public: + AbortingErrorCollector() {} + + virtual void AddError( + const string &filename, + const string &element_name, + const Message *message, + ErrorLocation location, + const string &error_message) { + GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << ": " + << error_message; + } + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector); +}; + +// A source tree containing only one file. +class SingletonSourceTree : public compiler::SourceTree { + public: + SingletonSourceTree(const string& filename, const string& contents) + : filename_(filename), contents_(contents) {} + + virtual io::ZeroCopyInputStream* Open(const string& filename) { + return filename == filename_ ? + new io::ArrayInputStream(contents_.data(), contents_.size()) : NULL; + } + + private: + const string filename_; + const string contents_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree); +}; + +const char *const kSourceLocationTestInput = + "syntax = \"proto2\";\n" + "message A {\n" + " optional int32 a = 1;\n" + " message B {\n" + " required double b = 1;\n" + " }\n" + "}\n" + "enum Indecision {\n" + " YES = 1;\n" + " NO = 2;\n" + " MAYBE = 3;\n" + "}\n" + "service S {\n" + " rpc Method(A) returns (A.B);\n" + // Put an empty line here to make the source location range match. + "\n" + "}\n" + "message MessageWithExtensions {\n" + " extensions 1000 to max;\n" + "}\n" + "extend MessageWithExtensions {\n" + " optional int32 int32_extension = 1001;\n" + "}\n" + "message C {\n" + " extend MessageWithExtensions {\n" + " optional C message_extension = 1002;\n" + " }\n" + "}\n"; + +class SourceLocationTest : public testing::Test { + public: + SourceLocationTest() + : source_tree_("/test/test.proto", kSourceLocationTestInput), + db_(&source_tree_), + pool_(&db_, &collector_) {} + + static string PrintSourceLocation(const SourceLocation &loc) { + return strings::Substitute("$0:$1-$2:$3", + 1 + loc.start_line, + 1 + loc.start_column, + 1 + loc.end_line, + 1 + loc.end_column); + } + + private: + AbortingErrorCollector collector_; + SingletonSourceTree source_tree_; + compiler::SourceTreeDescriptorDatabase db_; + + protected: + DescriptorPool pool_; +}; + +// TODO(adonovan): implement support for option fields and for +// subparts of declarations. + +TEST_F(SourceLocationTest, GetSourceLocation) { + SourceLocation loc; + + const FileDescriptor *file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + + const Descriptor *a_desc = file_desc->FindMessageTypeByName("A"); + EXPECT_TRUE(a_desc->GetSourceLocation(&loc)); + EXPECT_EQ("2:1-7:2", PrintSourceLocation(loc)); + + const Descriptor *a_b_desc = a_desc->FindNestedTypeByName("B"); + EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc)); + EXPECT_EQ("4:3-6:4", PrintSourceLocation(loc)); + + const EnumDescriptor *e_desc = file_desc->FindEnumTypeByName("Indecision"); + EXPECT_TRUE(e_desc->GetSourceLocation(&loc)); + EXPECT_EQ("8:1-12:2", PrintSourceLocation(loc)); + + const EnumValueDescriptor *yes_desc = e_desc->FindValueByName("YES"); + EXPECT_TRUE(yes_desc->GetSourceLocation(&loc)); + EXPECT_EQ("9:3-9:13", PrintSourceLocation(loc)); + + const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S"); + EXPECT_TRUE(s_desc->GetSourceLocation(&loc)); + EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc)); + + const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method"); + EXPECT_TRUE(m_desc->GetSourceLocation(&loc)); + EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc)); + +} + +TEST_F(SourceLocationTest, ExtensionSourceLocation) { + SourceLocation loc; + + const FileDescriptor *file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + + const FieldDescriptor *int32_extension_desc = + file_desc->FindExtensionByName("int32_extension"); + EXPECT_TRUE(int32_extension_desc->GetSourceLocation(&loc)); + EXPECT_EQ("21:3-21:41", PrintSourceLocation(loc)); + + const Descriptor *c_desc = file_desc->FindMessageTypeByName("C"); + EXPECT_TRUE(c_desc->GetSourceLocation(&loc)); + EXPECT_EQ("23:1-27:2", PrintSourceLocation(loc)); + + const FieldDescriptor *message_extension_desc = + c_desc->FindExtensionByName("message_extension"); + EXPECT_TRUE(message_extension_desc->GetSourceLocation(&loc)); + EXPECT_EQ("25:5-25:41", PrintSourceLocation(loc)); +} + +// Missing SourceCodeInfo doesn't cause crash: +TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) { + SourceLocation loc; + + const FileDescriptor *file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + + FileDescriptorProto proto; + file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo. + EXPECT_FALSE(proto.has_source_code_info()); + + DescriptorPool bad1_pool(&pool_); + const FileDescriptor* bad1_file_desc = + GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto)); + const Descriptor *bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A"); + EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc)); +} + +// Corrupt SourceCodeInfo doesn't cause crash: +TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) { + SourceLocation loc; + + const FileDescriptor *file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + + FileDescriptorProto proto; + file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo. + EXPECT_FALSE(proto.has_source_code_info()); + SourceCodeInfo_Location *loc_msg = + proto.mutable_source_code_info()->add_location(); + loc_msg->add_path(1); + loc_msg->add_path(2); + loc_msg->add_path(3); + loc_msg->add_span(4); + loc_msg->add_span(5); + loc_msg->add_span(6); + + DescriptorPool bad2_pool(&pool_); + const FileDescriptor* bad2_file_desc = + GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto)); + const Descriptor *bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A"); + EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc)); +} + +// =================================================================== + +const char* const kCopySourceCodeInfoToTestInput = + "syntax = \"proto2\";\n" + "message Foo {}\n"; + +// Required since source code information is not preserved by +// FileDescriptorTest. +class CopySourceCodeInfoToTest : public testing::Test { + public: + CopySourceCodeInfoToTest() + : source_tree_("/test/test.proto", kCopySourceCodeInfoToTestInput), + db_(&source_tree_), + pool_(&db_, &collector_) {} + + private: + AbortingErrorCollector collector_; + SingletonSourceTree source_tree_; + compiler::SourceTreeDescriptorDatabase db_; + + protected: + DescriptorPool pool_; +}; + +TEST_F(CopySourceCodeInfoToTest, CopyTo_DoesNotCopySourceCodeInfo) { + const FileDescriptor* file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + FileDescriptorProto file_desc_proto; + ASSERT_FALSE(file_desc_proto.has_source_code_info()); + + file_desc->CopyTo(&file_desc_proto); + EXPECT_FALSE(file_desc_proto.has_source_code_info()); +} + +TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) { + const FileDescriptor* file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + FileDescriptorProto file_desc_proto; + ASSERT_FALSE(file_desc_proto.has_source_code_info()); + + file_desc->CopySourceCodeInfoTo(&file_desc_proto); + const SourceCodeInfo& info = file_desc_proto.source_code_info(); + ASSERT_EQ(3, info.location_size()); + // Get the Foo message location + const SourceCodeInfo_Location& foo_location = info.location(1); + ASSERT_EQ(2, foo_location.path_size()); + EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0)); + EXPECT_EQ(0, foo_location.path(1)); // Foo is the first message defined + ASSERT_EQ(3, foo_location.span_size()); // Foo spans one line + EXPECT_EQ(1, foo_location.span(0)); // Foo is declared on line 1 + EXPECT_EQ(0, foo_location.span(1)); // Foo starts at column 0 + EXPECT_EQ(14, foo_location.span(2)); // Foo ends on column 14 +} + +// =================================================================== + } // namespace descriptor_unittest } // namespace protobuf diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc index c711a2d..81c709a 100644 --- a/src/google/protobuf/dynamic_message.cc +++ b/src/google/protobuf/dynamic_message.cc @@ -123,7 +123,9 @@ int FieldSpaceUsed(const FieldDescriptor* field) { case FD::CPPTYPE_FLOAT : return sizeof(float ); case FD::CPPTYPE_BOOL : return sizeof(bool ); case FD::CPPTYPE_ENUM : return sizeof(int ); - case FD::CPPTYPE_MESSAGE: return sizeof(Message*); + + case FD::CPPTYPE_MESSAGE: + return sizeof(Message*); case FD::CPPTYPE_STRING: switch (field->options().ctype()) { @@ -139,11 +141,42 @@ int FieldSpaceUsed(const FieldDescriptor* field) { return 0; } +// Compute the byte size of in-memory representation of the oneof fields +// in default oneof instance. +int OneofFieldSpaceUsed(const FieldDescriptor* field) { + typedef FieldDescriptor FD; // avoid line wrapping + switch (field->cpp_type()) { + case FD::CPPTYPE_INT32 : return sizeof(int32 ); + case FD::CPPTYPE_INT64 : return sizeof(int64 ); + case FD::CPPTYPE_UINT32 : return sizeof(uint32 ); + case FD::CPPTYPE_UINT64 : return sizeof(uint64 ); + case FD::CPPTYPE_DOUBLE : return sizeof(double ); + case FD::CPPTYPE_FLOAT : return sizeof(float ); + case FD::CPPTYPE_BOOL : return sizeof(bool ); + case FD::CPPTYPE_ENUM : return sizeof(int ); + + case FD::CPPTYPE_MESSAGE: + return sizeof(Message*); + + case FD::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: + return sizeof(string*); + } + break; + } + + GOOGLE_LOG(DFATAL) << "Can't get here."; + return 0; +} + inline int DivideRoundingUp(int i, int j) { return (i + (j - 1)) / j; } static const int kSafeAlignment = sizeof(uint64); +static const int kMaxOneofUnionSize = sizeof(uint64); inline int AlignTo(int offset, int alignment) { return DivideRoundingUp(offset, alignment) * alignment; @@ -166,6 +199,7 @@ class DynamicMessage : public Message { struct TypeInfo { int size; int has_bits_offset; + int oneof_case_offset; int unknown_fields_offset; int extensions_offset; @@ -178,7 +212,19 @@ class DynamicMessage : public Message { // important (the prototype must be deleted *before* the offsets). scoped_array offsets; scoped_ptr reflection; - scoped_ptr prototype; + // Don't use a scoped_ptr to hold the prototype: the destructor for + // DynamicMessage needs to know whether it is the prototype, and does so by + // looking back at this field. This would assume details about the + // implementation of scoped_ptr. + const DynamicMessage* prototype; + void* default_oneof_instance; + + TypeInfo() : prototype(NULL), default_oneof_instance(NULL) {} + + ~TypeInfo() { + delete prototype; + operator delete(default_oneof_instance); + } }; DynamicMessage(const TypeInfo* type_info); @@ -196,6 +242,7 @@ class DynamicMessage : public Message { Metadata GetMetadata() const; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage); @@ -233,6 +280,12 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info) const Descriptor* descriptor = type_info_->type; + // Initialize oneof cases. + for (int i = 0 ; i < descriptor->oneof_decl_count(); ++i) { + new(OffsetToPointer(type_info_->oneof_case_offset + sizeof(uint32) * i)) + uint32(0); + } + new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet; if (type_info_->extensions_offset != -1) { @@ -242,6 +295,9 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info) for (int i = 0; i < descriptor->field_count(); i++) { const FieldDescriptor* field = descriptor->field(i); void* field_ptr = OffsetToPointer(type_info_->offsets[i]); + if (field->containing_oneof()) { + continue; + } switch (field->cpp_type()) { #define HANDLE_TYPE(CPPTYPE, TYPE) \ case FieldDescriptor::CPPTYPE_##CPPTYPE: \ @@ -315,12 +371,35 @@ DynamicMessage::~DynamicMessage() { // We need to manually run the destructors for repeated fields and strings, // just as we ran their constructors in the the DynamicMessage constructor. + // We also need to manually delete oneof fields if it is set and is string + // or message. // Additionally, if any singular embedded messages have been allocated, we // need to delete them, UNLESS we are the prototype message of this type, // in which case any embedded messages are other prototypes and shouldn't // be touched. for (int i = 0; i < descriptor->field_count(); i++) { const FieldDescriptor* field = descriptor->field(i); + if (field->containing_oneof()) { + void* field_ptr = OffsetToPointer( + type_info_->oneof_case_offset + + sizeof(uint32) * field->containing_oneof()->index()); + if (*(reinterpret_cast(field_ptr)) == + field->number()) { + field_ptr = OffsetToPointer(type_info_->offsets[ + descriptor->field_count() + field->containing_oneof()->index()]); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: + delete *reinterpret_cast(field_ptr); + break; + } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + delete *reinterpret_cast(field_ptr); + } + } + continue; + } void* field_ptr = OffsetToPointer(type_info_->offsets[i]); if (field->is_repeated()) { @@ -368,11 +447,12 @@ DynamicMessage::~DynamicMessage() { break; } } - } else if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) && - !is_prototype()) { - Message* message = *reinterpret_cast(field_ptr); - if (message != NULL) { - delete message; + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (!is_prototype()) { + Message* message = *reinterpret_cast(field_ptr); + if (message != NULL) { + delete message; + } } } } @@ -389,6 +469,10 @@ void DynamicMessage::CrossLinkPrototypes() { for (int i = 0; i < descriptor->field_count(); i++) { const FieldDescriptor* field = descriptor->field(i); void* field_ptr = OffsetToPointer(type_info_->offsets[i]); + if (field->containing_oneof()) { + field_ptr = reinterpret_cast( + type_info_->default_oneof_instance) + type_info_->offsets[i]; + } if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && !field->is_repeated()) { @@ -403,7 +487,7 @@ void DynamicMessage::CrossLinkPrototypes() { } Message* DynamicMessage::New() const { - void* new_base = reinterpret_cast(operator new(type_info_->size)); + void* new_base = operator new(type_info_->size); memset(new_base, 0, type_info_->size); return new(new_base) DynamicMessage(type_info_); } @@ -416,7 +500,9 @@ void DynamicMessage::SetCachedSize(int size) const { // This is theoretically not thread-compatible, but in practice it works // because if multiple threads write this simultaneously, they will be // writing the exact same value. + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); cached_byte_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); } Metadata DynamicMessage::GetMetadata() const { @@ -446,6 +532,9 @@ DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool) DynamicMessageFactory::~DynamicMessageFactory() { for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin(); iter != prototypes_->map_.end(); ++iter) { + DeleteDefaultOneofInstance(iter->second->type, + iter->second->offsets.get(), + iter->second->default_oneof_instance); delete iter->second; } } @@ -465,7 +554,7 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( const DynamicMessage::TypeInfo** target = &prototypes_->map_[type]; if (*target != NULL) { // Already exists. - return (*target)->prototype.get(); + return (*target)->prototype; } DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo; @@ -484,7 +573,7 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( // or not that field is set. // Compute size and offsets. - int* offsets = new int[type->field_count()]; + int* offsets = new int[type->field_count() + type->oneof_decl_count()]; type_info->offsets.reset(offsets); // Decide all field offsets by packing in order. @@ -500,6 +589,13 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( size += has_bits_array_size * sizeof(uint32); size = AlignOffset(size); + // The oneof_case, if any. It is an array of uint32s. + if (type->oneof_decl_count() > 0) { + type_info->oneof_case_offset = size; + size += type->oneof_decl_count() * sizeof(uint32); + size = AlignOffset(size); + } + // The ExtensionSet, if any. if (type->extension_range_count() > 0) { type_info->extensions_offset = size; @@ -513,10 +609,20 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( // All the fields. for (int i = 0; i < type->field_count(); i++) { // Make sure field is aligned to avoid bus errors. - int field_size = FieldSpaceUsed(type->field(i)); - size = AlignTo(size, min(kSafeAlignment, field_size)); - offsets[i] = size; - size += field_size; + // Oneof fields do not use any space. + if (!type->field(i)->containing_oneof()) { + int field_size = FieldSpaceUsed(type->field(i)); + size = AlignTo(size, min(kSafeAlignment, field_size)); + offsets[i] = size; + size += field_size; + } + } + + // The oneofs. + for (int i = 0; i < type->oneof_decl_count(); i++) { + size = AlignTo(size, kSafeAlignment); + offsets[type->field_count() + i] = size; + size += kMaxOneofUnionSize; } // Add the UnknownFieldSet to the end. @@ -533,26 +639,126 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( void* base = operator new(size); memset(base, 0, size); DynamicMessage* prototype = new(base) DynamicMessage(type_info); - type_info->prototype.reset(prototype); + type_info->prototype = prototype; // Construct the reflection object. - type_info->reflection.reset( - new GeneratedMessageReflection( - type_info->type, - type_info->prototype.get(), - type_info->offsets.get(), - type_info->has_bits_offset, - type_info->unknown_fields_offset, - type_info->extensions_offset, - type_info->pool, - this, - type_info->size)); - + if (type->oneof_decl_count() > 0) { + // Compute the size of default oneof instance and offsets of default + // oneof fields. + int oneof_size = 0; + for (int i = 0; i < type->oneof_decl_count(); i++) { + for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = type->oneof_decl(i)->field(j); + int field_size = OneofFieldSpaceUsed(field); + oneof_size = AlignTo(oneof_size, min(kSafeAlignment, field_size)); + offsets[field->index()] = oneof_size; + oneof_size += field_size; + } + } + // Construct default oneof instance. + type_info->default_oneof_instance = ::operator new(oneof_size); + ConstructDefaultOneofInstance(type_info->type, + type_info->offsets.get(), + type_info->default_oneof_instance); + type_info->reflection.reset( + new GeneratedMessageReflection( + type_info->type, + type_info->prototype, + type_info->offsets.get(), + type_info->has_bits_offset, + type_info->unknown_fields_offset, + type_info->extensions_offset, + type_info->default_oneof_instance, + type_info->oneof_case_offset, + type_info->pool, + this, + type_info->size)); + } else { + type_info->reflection.reset( + new GeneratedMessageReflection( + type_info->type, + type_info->prototype, + type_info->offsets.get(), + type_info->has_bits_offset, + type_info->unknown_fields_offset, + type_info->extensions_offset, + type_info->pool, + this, + type_info->size)); + } // Cross link prototypes. prototype->CrossLinkPrototypes(); return prototype; } +void DynamicMessageFactory::ConstructDefaultOneofInstance( + const Descriptor* type, + const int offsets[], + void* default_oneof_instance) { + for (int i = 0; i < type->oneof_decl_count(); i++) { + for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = type->oneof_decl(i)->field(j); + void* field_ptr = reinterpret_cast( + default_oneof_instance) + offsets[field->index()]; + switch (field->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + new(field_ptr) TYPE(field->default_value_##TYPE()); \ + break; + + HANDLE_TYPE(INT32 , int32 ); + HANDLE_TYPE(INT64 , int64 ); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT , float ); + HANDLE_TYPE(BOOL , bool ); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_ENUM: + new(field_ptr) int(field->default_value_enum()->number()); + break; + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: + if (field->has_default_value()) { + new(field_ptr) const string*(&field->default_value_string()); + } else { + new(field_ptr) string*( + const_cast(&internal::GetEmptyString())); + } + break; + } + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: { + new(field_ptr) Message*(NULL); + break; + } + } + } + } +} + +void DynamicMessageFactory::DeleteDefaultOneofInstance( + const Descriptor* type, + const int offsets[], + void* default_oneof_instance) { + for (int i = 0; i < type->oneof_decl_count(); i++) { + for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = type->oneof_decl(i)->field(j); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: + break; + } + } + } + } +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h index 81dd2c6..a09593c 100644 --- a/src/google/protobuf/dynamic_message.h +++ b/src/google/protobuf/dynamic_message.h @@ -38,6 +38,8 @@ #ifndef GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ #define GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ +#include + #include #include @@ -68,7 +70,7 @@ class DescriptorPool; // descriptor.h class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory { public: // Construct a DynamicMessageFactory that will search for extensions in - // the DescriptorPool in which the exendee is defined. + // the DescriptorPool in which the extendee is defined. DynamicMessageFactory(); // Construct a DynamicMessageFactory that will search for extensions in @@ -102,7 +104,7 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory { // object. The returned object remains property of the factory and will // be destroyed when the factory is destroyed. Also, any objects created // by calling the prototype's New() method share some data with the - // prototype, so these must be destoyed before the DynamicMessageFactory + // prototype, so these must be destroyed before the DynamicMessageFactory // is destroyed. // // The given descriptor must outlive the returned message, and hence must @@ -127,6 +129,16 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory { friend class DynamicMessage; const Message* GetPrototypeNoLock(const Descriptor* type); + // Construct default oneof instance for reflection usage if oneof + // is defined. + static void ConstructDefaultOneofInstance(const Descriptor* type, + const int offsets[], + void* default_oneof_instance); + // Delete default oneof instance. Called by ~DynamicMessageFactory. + static void DeleteDefaultOneofInstance(const Descriptor* type, + const int offsets[], + void* default_oneof_instance); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory); }; diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc index 41b89ab..a7866d9 100644 --- a/src/google/protobuf/dynamic_message_unittest.cc +++ b/src/google/protobuf/dynamic_message_unittest.cc @@ -63,6 +63,8 @@ class DynamicMessageTest : public testing::Test { const Message* extensions_prototype_; const Descriptor* packed_descriptor_; const Message* packed_prototype_; + const Descriptor* oneof_descriptor_; + const Message* oneof_prototype_; DynamicMessageTest(): factory_(&pool_) {} @@ -73,11 +75,15 @@ class DynamicMessageTest : public testing::Test { // unittest_import.proto. FileDescriptorProto unittest_file; FileDescriptorProto unittest_import_file; + FileDescriptorProto unittest_import_public_file; unittest::TestAllTypes::descriptor()->file()->CopyTo(&unittest_file); unittest_import::ImportMessage::descriptor()->file()->CopyTo( &unittest_import_file); + unittest_import::PublicImportMessage::descriptor()->file()->CopyTo( + &unittest_import_public_file); + ASSERT_TRUE(pool_.BuildFile(unittest_import_public_file) != NULL); ASSERT_TRUE(pool_.BuildFile(unittest_import_file) != NULL); ASSERT_TRUE(pool_.BuildFile(unittest_file) != NULL); @@ -94,6 +100,11 @@ class DynamicMessageTest : public testing::Test { pool_.FindMessageTypeByName("protobuf_unittest.TestPackedTypes"); ASSERT_TRUE(packed_descriptor_ != NULL); packed_prototype_ = factory_.GetPrototype(packed_descriptor_); + + oneof_descriptor_ = + pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2"); + ASSERT_TRUE(oneof_descriptor_ != NULL); + oneof_prototype_ = factory_.GetPrototype(oneof_descriptor_); } }; @@ -143,6 +154,63 @@ TEST_F(DynamicMessageTest, PackedFields) { reflection_tester.ExpectPackedFieldsSetViaReflection(*message); } +TEST_F(DynamicMessageTest, Oneof) { + // Check that oneof fields work properly. + scoped_ptr message(oneof_prototype_->New()); + + // Check default values. + const Descriptor* descriptor = message->GetDescriptor(); + const Reflection* reflection = message->GetReflection(); + EXPECT_EQ(0, reflection->GetInt32( + *message, descriptor->FindFieldByName("foo_int"))); + EXPECT_EQ("", reflection->GetString( + *message, descriptor->FindFieldByName("foo_string"))); + EXPECT_EQ("", reflection->GetString( + *message, descriptor->FindFieldByName("foo_cord"))); + EXPECT_EQ("", reflection->GetString( + *message, descriptor->FindFieldByName("foo_string_piece"))); + EXPECT_EQ("", reflection->GetString( + *message, descriptor->FindFieldByName("foo_bytes"))); + EXPECT_EQ(unittest::TestOneof2::FOO, reflection->GetEnum( + *message, descriptor->FindFieldByName("foo_enum"))->number()); + const Descriptor* nested_descriptor; + const Message* nested_prototype; + nested_descriptor = + pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.NestedMessage"); + nested_prototype = factory_.GetPrototype(nested_descriptor); + EXPECT_EQ(nested_prototype, + &reflection->GetMessage( + *message, descriptor->FindFieldByName("foo_message"))); + const Descriptor* foogroup_descriptor; + const Message* foogroup_prototype; + foogroup_descriptor = + pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.FooGroup"); + foogroup_prototype = factory_.GetPrototype(foogroup_descriptor); + EXPECT_EQ(foogroup_prototype, + &reflection->GetMessage( + *message, descriptor->FindFieldByName("foogroup"))); + EXPECT_NE(foogroup_prototype, + &reflection->GetMessage( + *message, descriptor->FindFieldByName("foo_lazy_message"))); + EXPECT_EQ(5, reflection->GetInt32( + *message, descriptor->FindFieldByName("bar_int"))); + EXPECT_EQ("STRING", reflection->GetString( + *message, descriptor->FindFieldByName("bar_string"))); + EXPECT_EQ("CORD", reflection->GetString( + *message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_EQ("SPIECE", reflection->GetString( + *message, descriptor->FindFieldByName("bar_string_piece"))); + EXPECT_EQ("BYTES", reflection->GetString( + *message, descriptor->FindFieldByName("bar_bytes"))); + EXPECT_EQ(unittest::TestOneof2::BAR, reflection->GetEnum( + *message, descriptor->FindFieldByName("bar_enum"))->number()); + + // Check set functions. + TestUtil::ReflectionTester reflection_tester(oneof_descriptor_); + reflection_tester.SetOneofViaReflection(message.get()); + reflection_tester.ExpectOneofSetViaReflection(*message); +} + TEST_F(DynamicMessageTest, SpaceUsed) { // Test that SpaceUsed() works properly diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 6084885..81ff89f 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -38,10 +38,9 @@ #include #include #include -#include #include #include -#include +#include namespace google { namespace protobuf { @@ -58,6 +57,22 @@ inline WireFormatLite::CppType cpp_type(FieldType type) { return WireFormatLite::FieldTypeToCppType(real_type(type)); } +inline bool is_packable(WireFormatLite::WireType type) { + switch (type) { + case WireFormatLite::WIRETYPE_VARINT: + case WireFormatLite::WIRETYPE_FIXED64: + case WireFormatLite::WIRETYPE_FIXED32: + return true; + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: + case WireFormatLite::WIRETYPE_START_GROUP: + case WireFormatLite::WIRETYPE_END_GROUP: + return false; + + // Do not add a default statement. Let the compiler complain when someone + // adds a new wire type. + } +} + // Registry stuff. typedef hash_map, ExtensionInfo> ExtensionRegistry; @@ -71,7 +86,7 @@ void DeleteRegistry() { void InitRegistry() { registry_ = new ExtensionRegistry; - internal::OnShutdown(&DeleteRegistry); + OnShutdown(&DeleteRegistry); } // This function is only called at startup, so there is no need for thread- @@ -180,12 +195,35 @@ bool ExtensionSet::Has(int number) const { return !iter->second.is_cleared; } +int ExtensionSet::NumExtensions() const { + int result = 0; + for (map::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + if (!iter->second.is_cleared) { + ++result; + } + } + return result; +} + int ExtensionSet::ExtensionSize(int number) const { map::const_iterator iter = extensions_.find(number); if (iter == extensions_.end()) return false; return iter->second.GetSize(); } +FieldType ExtensionSet::ExtensionType(int number) const { + map::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end()) { + GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (1). "; + return 0; + } + if (iter->second.is_cleared) { + GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (2). "; + } + return iter->second.type; +} + void ExtensionSet::ClearExtension(int number) { map::iterator iter = extensions_.find(number); if (iter == extensions_.end()) return; @@ -281,6 +319,80 @@ PRIMITIVE_ACCESSORS( BOOL, bool, Bool) #undef PRIMITIVE_ACCESSORS +const void* ExtensionSet::GetRawRepeatedField(int number, + const void* default_value) const { + map::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end()) { + return default_value; + } + // We assume that all the RepeatedField<>* pointers have the same + // size and alignment within the anonymous union in Extension. + return iter->second.repeated_int32_value; +} + +void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type, + bool packed, + const FieldDescriptor* desc) { + Extension* extension; + + // We instantiate an empty Repeated{,Ptr}Field if one doesn't exist for this + // extension. + if (MaybeNewExtension(number, desc, &extension)) { + extension->is_repeated = true; + extension->type = field_type; + extension->is_packed = packed; + + switch (WireFormatLite::FieldTypeToCppType( + static_cast(field_type))) { + case WireFormatLite::CPPTYPE_INT32: + extension->repeated_int32_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_INT64: + extension->repeated_int64_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_UINT32: + extension->repeated_uint32_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_UINT64: + extension->repeated_uint64_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_DOUBLE: + extension->repeated_double_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_FLOAT: + extension->repeated_float_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_BOOL: + extension->repeated_bool_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_ENUM: + extension->repeated_enum_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_STRING: + extension->repeated_string_value = new RepeatedPtrField< ::std::string>(); + break; + case WireFormatLite::CPPTYPE_MESSAGE: + extension->repeated_message_value = new RepeatedPtrField(); + break; + } + } + + // We assume that all the RepeatedField<>* pointers have the same + // size and alignment within the anonymous union in Extension. + return extension->repeated_int32_value; +} + +// Compatible version using old call signature. Does not create extensions when +// the don't already exist; instead, just GOOGLE_CHECK-fails. +void* ExtensionSet::MutableRawRepeatedField(int number) { + map::iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter == extensions_.end()) << "Extension not found."; + // We assume that all the RepeatedField<>* pointers have the same + // size and alignment within the anonymous union in Extension. + return iter->second.repeated_int32_value; +} + + // ------------------------------------------------------------------- // Enums @@ -410,7 +522,11 @@ const MessageLite& ExtensionSet::GetMessage( return default_value; } else { GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); - return *iter->second.message_value; + if (iter->second.is_lazy) { + return iter->second.lazymessage_value->GetMessage(default_value); + } else { + return *iter->second.message_value; + } } } @@ -427,12 +543,19 @@ MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, extension->type = type; GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); extension->is_repeated = false; + extension->is_lazy = false; extension->message_value = prototype.New(); + extension->is_cleared = false; + return extension->message_value; } else { GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + extension->is_cleared = false; + if (extension->is_lazy) { + return extension->lazymessage_value->MutableMessage(prototype); + } else { + return extension->message_value; + } } - extension->is_cleared = false; - return extension->message_value; } // Defined in extension_set_heavy.cc. @@ -440,6 +563,56 @@ MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, // const Descriptor* message_type, // MessageFactory* factory) +void ExtensionSet::SetAllocatedMessage(int number, FieldType type, + const FieldDescriptor* descriptor, + MessageLite* message) { + if (message == NULL) { + ClearExtension(number); + return; + } + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); + extension->is_repeated = false; + extension->is_lazy = false; + extension->message_value = message; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + if (extension->is_lazy) { + extension->lazymessage_value->SetAllocatedMessage(message); + } else { + delete extension->message_value; + extension->message_value = message; + } + } + extension->is_cleared = false; +} + +MessageLite* ExtensionSet::ReleaseMessage(int number, + const MessageLite& prototype) { + map::iterator iter = extensions_.find(number); + if (iter == extensions_.end()) { + // Not present. Return NULL. + return NULL; + } else { + GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); + MessageLite* ret = NULL; + if (iter->second.is_lazy) { + ret = iter->second.lazymessage_value->ReleaseMessage(prototype); + delete iter->second.lazymessage_value; + } else { + ret = iter->second.message_value; + } + extensions_.erase(number); + return ret; + } +} + +// Defined in extension_set_heavy.cc. +// MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, +// MessageFactory* factory); + const MessageLite& ExtensionSet::GetRepeatedMessage( int number, int index) const { map::const_iterator iter = extensions_.find(number); @@ -472,7 +645,7 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type, // RepeatedPtrField does not know how to Add() since it cannot // allocate an abstract object, so we have to be tricky. MessageLite* result = extension->repeated_message_value - ->AddFromCleared >(); + ->AddFromCleared >(); if (result == NULL) { result = prototype.New(); extension->repeated_message_value->AddAllocated(result); @@ -528,6 +701,16 @@ void ExtensionSet::RemoveLast(int number) { } } +MessageLite* ExtensionSet::ReleaseLast(int number) { + map::iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; + + Extension* extension = &iter->second; + GOOGLE_DCHECK(extension->is_repeated); + GOOGLE_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE); + return extension->repeated_message_value->ReleaseLast(); +} + void ExtensionSet::SwapElements(int number, int index1, int index2) { map::iterator iter = extensions_.find(number); GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; @@ -590,9 +773,11 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) { if (is_new) { // Extension did not already exist in set. extension->type = other_extension.type; + extension->is_packed = other_extension.is_packed; extension->is_repeated = true; } else { GOOGLE_DCHECK_EQ(extension->type, other_extension.type); + GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed); GOOGLE_DCHECK(extension->is_repeated); } @@ -663,12 +848,55 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) { *other_extension.string_value, other_extension.descriptor); break; - case WireFormatLite::CPPTYPE_MESSAGE: - MutableMessage(iter->first, other_extension.type, - *other_extension.message_value, - other_extension.descriptor) - ->CheckTypeAndMergeFrom(*other_extension.message_value); + case WireFormatLite::CPPTYPE_MESSAGE: { + Extension* extension; + bool is_new = MaybeNewExtension(iter->first, + other_extension.descriptor, + &extension); + if (is_new) { + extension->type = other_extension.type; + extension->is_packed = other_extension.is_packed; + extension->is_repeated = false; + if (other_extension.is_lazy) { + extension->is_lazy = true; + extension->lazymessage_value = + other_extension.lazymessage_value->New(); + extension->lazymessage_value->MergeFrom( + *other_extension.lazymessage_value); + } else { + extension->is_lazy = false; + extension->message_value = + other_extension.message_value->New(); + extension->message_value->CheckTypeAndMergeFrom( + *other_extension.message_value); + } + } else { + GOOGLE_DCHECK_EQ(extension->type, other_extension.type); + GOOGLE_DCHECK_EQ(extension->is_packed,other_extension.is_packed); + GOOGLE_DCHECK(!extension->is_repeated); + if (other_extension.is_lazy) { + if (extension->is_lazy) { + extension->lazymessage_value->MergeFrom( + *other_extension.lazymessage_value); + } else { + extension->message_value->CheckTypeAndMergeFrom( + other_extension.lazymessage_value->GetMessage( + *extension->message_value)); + } + } else { + if (extension->is_lazy) { + extension->lazymessage_value->MutableMessage( + *other_extension.message_value)->CheckTypeAndMergeFrom( + *other_extension.message_value); + } else { + extension->message_value->CheckTypeAndMergeFrom( + *other_extension.message_value); + } + } + } + extension->is_cleared = false; break; + } } } } @@ -679,6 +907,36 @@ void ExtensionSet::Swap(ExtensionSet* x) { extensions_.swap(x->extensions_); } +void ExtensionSet::SwapExtension(ExtensionSet* other, + int number) { + if (this == other) return; + map::iterator this_iter = extensions_.find(number); + map::iterator other_iter = other->extensions_.find(number); + + if (this_iter == extensions_.end() && + other_iter == other->extensions_.end()) { + return; + } + + if (this_iter != extensions_.end() && + other_iter != other->extensions_.end()) { + std::swap(this_iter->second, other_iter->second); + return; + } + + if (this_iter == extensions_.end()) { + extensions_.insert(make_pair(number, other_iter->second)); + other->extensions_.erase(number); + return; + } + + if (other_iter == other->extensions_.end()) { + other->extensions_.insert(make_pair(number, this_iter->second)); + extensions_.erase(number); + return; + } +} + bool ExtensionSet::IsInitialized() const { // Extensions are never required. However, we need to check that all // embedded messages are initialized. @@ -694,7 +952,11 @@ bool ExtensionSet::IsInitialized() const { } } else { if (!extension.is_cleared) { - if (!extension.message_value->IsInitialized()) return false; + if (extension.is_lazy) { + if (!extension.lazymessage_value->IsInitialized()) return false; + } else { + if (!extension.message_value->IsInitialized()) return false; + } } } } @@ -703,27 +965,60 @@ bool ExtensionSet::IsInitialized() const { return true; } +bool ExtensionSet::FindExtensionInfoFromTag( + uint32 tag, ExtensionFinder* extension_finder, int* field_number, + ExtensionInfo* extension, bool* was_packed_on_wire) { + *field_number = WireFormatLite::GetTagFieldNumber(tag); + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + return FindExtensionInfoFromFieldNumber(wire_type, *field_number, + extension_finder, extension, + was_packed_on_wire); +} + +bool ExtensionSet::FindExtensionInfoFromFieldNumber( + int wire_type, int field_number, ExtensionFinder* extension_finder, + ExtensionInfo* extension, bool* was_packed_on_wire) { + if (!extension_finder->Find(field_number, extension)) { + return false; + } + + WireFormatLite::WireType expected_wire_type = + WireFormatLite::WireTypeForFieldType(real_type(extension->type)); + + // Check if this is a packed field. + *was_packed_on_wire = false; + if (extension->is_repeated && + wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED && + is_packable(expected_wire_type)) { + *was_packed_on_wire = true; + return true; + } + // Otherwise the wire type must match. + return expected_wire_type == wire_type; +} + bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, ExtensionFinder* extension_finder, FieldSkipper* field_skipper) { - int number = WireFormatLite::GetTagFieldNumber(tag); - WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); - + int number; + bool was_packed_on_wire; ExtensionInfo extension; - bool is_unknown; - if (!extension_finder->Find(number, &extension)) { - is_unknown = true; - } else if (extension.is_packed) { - is_unknown = (wire_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + if (!FindExtensionInfoFromTag( + tag, extension_finder, &number, &extension, &was_packed_on_wire)) { + return field_skipper->SkipField(input, tag); } else { - WireFormatLite::WireType expected_wire_type = - WireFormatLite::WireTypeForFieldType(real_type(extension.type)); - is_unknown = (wire_type != expected_wire_type); + return ParseFieldWithExtensionInfo( + number, was_packed_on_wire, extension, input, field_skipper); } +} - if (is_unknown) { - field_skipper->SkipField(input, tag); - } else if (extension.is_packed) { +bool ExtensionSet::ParseFieldWithExtensionInfo( + int number, bool was_packed_on_wire, const ExtensionInfo& extension, + io::CodedInputStream* input, + FieldSkipper* field_skipper) { + // Explicitly not read extension.is_packed, instead check whether the field + // was encoded in packed form on the wire. + if (was_packed_on_wire) { uint32 size; if (!input->ReadVarint32(&size)) return false; io::CodedInputStream::Limit limit = input->PushLimit(size); @@ -737,7 +1032,8 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \ input, &value)) return false; \ Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ - true, value, extension.descriptor); \ + extension.is_packed, value, \ + extension.descriptor); \ } \ break @@ -763,8 +1059,8 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, input, &value)) return false; if (extension.enum_validity_check.func( extension.enum_validity_check.arg, value)) { - AddEnum(number, WireFormatLite::TYPE_ENUM, true, value, - extension.descriptor); + AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, + value, extension.descriptor); } } break; @@ -786,9 +1082,10 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, if (!WireFormatLite::ReadPrimitive< \ CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \ input, &value)) return false; \ - if (extension.is_repeated) { \ + if (extension.is_repeated) { \ Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ - false, value, extension.descriptor); \ + extension.is_packed, value, \ + extension.descriptor); \ } else { \ Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ extension.descriptor); \ @@ -820,7 +1117,7 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, // Invalid value. Treat as unknown. field_skipper->SkipUnknownEnum(number, value); } else if (extension.is_repeated) { - AddEnum(number, WireFormatLite::TYPE_ENUM, false, value, + AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value, extension.descriptor); } else { SetEnum(number, WireFormatLite::TYPE_ENUM, value, @@ -840,8 +1137,8 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, case WireFormatLite::TYPE_BYTES: { string* value = extension.is_repeated ? - AddString(number, WireFormatLite::TYPE_STRING, extension.descriptor) : - MutableString(number, WireFormatLite::TYPE_STRING, + AddString(number, WireFormatLite::TYPE_BYTES, extension.descriptor) : + MutableString(number, WireFormatLite::TYPE_BYTES, extension.descriptor); if (!WireFormatLite::ReadBytes(input, value)) return false; break; @@ -879,125 +1176,24 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, return ParseField(tag, input, &finder, &skipper); } +bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, + const MessageLite* containing_type, + io::CodedOutputStream* unknown_fields) { + CodedOutputStreamFieldSkipper skipper(unknown_fields); + GeneratedExtensionFinder finder(containing_type); + return ParseField(tag, input, &finder, &skipper); +} + // Defined in extension_set_heavy.cc. // bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, // const MessageLite* containing_type, // UnknownFieldSet* unknown_fields) -bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, - ExtensionFinder* extension_finder, - FieldSkipper* field_skipper) { - while (true) { - uint32 tag = input->ReadTag(); - switch (tag) { - case 0: - return true; - case WireFormatLite::kMessageSetItemStartTag: - if (!ParseMessageSetItem(input, extension_finder, field_skipper)) { - return false; - } - break; - default: - if (!ParseField(tag, input, extension_finder, field_skipper)) { - return false; - } - break; - } - } -} - -bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, - const MessageLite* containing_type) { - FieldSkipper skipper; - GeneratedExtensionFinder finder(containing_type); - return ParseMessageSet(input, &finder, &skipper); -} - // Defined in extension_set_heavy.cc. // bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, // const MessageLite* containing_type, // UnknownFieldSet* unknown_fields); -bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input, - ExtensionFinder* extension_finder, - FieldSkipper* field_skipper) { - // TODO(kenton): It would be nice to share code between this and - // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the - // differences would be hard to factor out. - - // This method parses a group which should contain two fields: - // required int32 type_id = 2; - // required data message = 3; - - // Once we see a type_id, we'll construct a fake tag for this extension - // which is the tag it would have had under the proto2 extensions wire - // format. - uint32 fake_tag = 0; - - // If we see message data before the type_id, we'll append it to this so - // we can parse it later. This will probably never happen in practice, - // as no MessageSet encoder I know of writes the message before the type ID. - // But, it's technically valid so we should allow it. - // TODO(kenton): Use a Cord instead? Do I care? - string message_data; - - while (true) { - uint32 tag = input->ReadTag(); - if (tag == 0) return false; - - switch (tag) { - case WireFormatLite::kMessageSetTypeIdTag: { - uint32 type_id; - if (!input->ReadVarint32(&type_id)) return false; - fake_tag = WireFormatLite::MakeTag(type_id, - WireFormatLite::WIRETYPE_LENGTH_DELIMITED); - - if (!message_data.empty()) { - // We saw some message data before the type_id. Have to parse it - // now. - io::CodedInputStream sub_input( - reinterpret_cast(message_data.data()), - message_data.size()); - if (!ParseField(fake_tag, &sub_input, - extension_finder, field_skipper)) { - return false; - } - message_data.clear(); - } - - break; - } - - case WireFormatLite::kMessageSetMessageTag: { - if (fake_tag == 0) { - // We haven't seen a type_id yet. Append this data to message_data. - string temp; - uint32 length; - if (!input->ReadVarint32(&length)) return false; - if (!input->ReadString(&temp, length)) return false; - message_data.append(temp); - } else { - // Already saw type_id, so we can parse this directly. - if (!ParseField(fake_tag, input, - extension_finder, field_skipper)) { - return false; - } - } - - break; - } - - case WireFormatLite::kMessageSetItemEndTag: { - return true; - } - - default: { - if (!field_skipper->SkipField(input, tag)) return false; - } - } - } -} - void ExtensionSet::SerializeWithCachedSizes( int start_field_number, int end_field_number, io::CodedOutputStream* output) const { @@ -1009,14 +1205,6 @@ void ExtensionSet::SerializeWithCachedSizes( } } -void ExtensionSet::SerializeMessageSetWithCachedSizes( - io::CodedOutputStream* output) const { - map::const_iterator iter; - for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) { - iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output); - } -} - int ExtensionSet::ByteSize() const { int total_size = 0; @@ -1028,17 +1216,6 @@ int ExtensionSet::ByteSize() const { return total_size; } -int ExtensionSet::MessageSetByteSize() const { - int total_size = 0; - - for (map::const_iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { - total_size += iter->second.MessageSetItemByteSize(iter->first); - } - - return total_size; -} - // Defined in extension_set_heavy.cc. // int ExtensionSet::SpaceUsedExcludingSelf() const @@ -1082,7 +1259,11 @@ void ExtensionSet::Extension::Clear() { string_value->clear(); break; case WireFormatLite::CPPTYPE_MESSAGE: - message_value->Clear(); + if (is_lazy) { + lazymessage_value->Clear(); + } else { + message_value->Clear(); + } break; default: // No need to do anything. Get*() will return the default value @@ -1194,40 +1375,18 @@ void ExtensionSet::Extension::SerializeFieldWithCachedSizes( HANDLE_TYPE( BYTES, Bytes, *string_value); HANDLE_TYPE( ENUM, Enum, enum_value); HANDLE_TYPE( GROUP, Group, *message_value); - HANDLE_TYPE( MESSAGE, Message, *message_value); #undef HANDLE_TYPE + case WireFormatLite::TYPE_MESSAGE: + if (is_lazy) { + lazymessage_value->WriteMessage(number, output); + } else { + WireFormatLite::WriteMessage(number, *message_value, output); + } + break; } } } -void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes( - int number, - io::CodedOutputStream* output) const { - if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { - // Not a valid MessageSet extension, but serialize it the normal way. - SerializeFieldWithCachedSizes(number, output); - return; - } - - if (is_cleared) return; - - // Start group. - output->WriteTag(WireFormatLite::kMessageSetItemStartTag); - - // Write type ID. - WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber, - number, - output); - // Write message. - WireFormatLite::WriteMessageMaybeToArray( - WireFormatLite::kMessageSetMessageNumber, - *message_value, - output); - - // End group. - output->WriteTag(WireFormatLite::kMessageSetItemEndTag); -} - int ExtensionSet::Extension::ByteSize(int number) const { int result = 0; @@ -1341,8 +1500,16 @@ int ExtensionSet::Extension::ByteSize(int number) const { HANDLE_TYPE( BYTES, Bytes, *string_value); HANDLE_TYPE( ENUM, Enum, enum_value); HANDLE_TYPE( GROUP, Group, *message_value); - HANDLE_TYPE( MESSAGE, Message, *message_value); #undef HANDLE_TYPE + case WireFormatLite::TYPE_MESSAGE: { + if (is_lazy) { + int size = lazymessage_value->ByteSize(); + result += io::CodedOutputStream::VarintSize32(size) + size; + } else { + result += WireFormatLite::MessageSize(*message_value); + } + break; + } // Stuff with fixed size. #define HANDLE_TYPE(UPPERCASE, CAMELCASE) \ @@ -1363,29 +1530,6 @@ int ExtensionSet::Extension::ByteSize(int number) const { return result; } -int ExtensionSet::Extension::MessageSetItemByteSize(int number) const { - if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { - // Not a valid MessageSet extension, but compute the byte size for it the - // normal way. - return ByteSize(number); - } - - if (is_cleared) return 0; - - int our_size = WireFormatLite::kMessageSetItemTagsSize; - - // type_id - our_size += io::CodedOutputStream::VarintSize32(number); - - // message - int message_size = message_value->ByteSize(); - - our_size += io::CodedOutputStream::VarintSize32(message_size); - our_size += message_size; - - return our_size; -} - int ExtensionSet::Extension::GetSize() const { GOOGLE_DCHECK(is_repeated); switch (cpp_type(type)) { @@ -1436,7 +1580,11 @@ void ExtensionSet::Extension::Free() { delete string_value; break; case WireFormatLite::CPPTYPE_MESSAGE: - delete message_value; + if (is_lazy) { + delete lazymessage_value; + } else { + delete message_value; + } break; default: break; @@ -1447,6 +1595,56 @@ void ExtensionSet::Extension::Free() { // Defined in extension_set_heavy.cc. // int ExtensionSet::Extension::SpaceUsedExcludingSelf() const +// ================================================================== +// Default repeated field instances for iterator-compatible accessors + +const RepeatedStringTypeTraits::RepeatedFieldType* +RepeatedStringTypeTraits::default_repeated_field_ = NULL; + +const RepeatedMessageGenericTypeTraits::RepeatedFieldType* +RepeatedMessageGenericTypeTraits::default_repeated_field_ = NULL; + +#define PROTOBUF_DEFINE_DEFAULT_REPEATED(TYPE) \ + const RepeatedField* \ + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_##TYPE##_ = NULL; + +PROTOBUF_DEFINE_DEFAULT_REPEATED(int32) +PROTOBUF_DEFINE_DEFAULT_REPEATED(int64) +PROTOBUF_DEFINE_DEFAULT_REPEATED(uint32) +PROTOBUF_DEFINE_DEFAULT_REPEATED(uint64) +PROTOBUF_DEFINE_DEFAULT_REPEATED(double) +PROTOBUF_DEFINE_DEFAULT_REPEATED(float) +PROTOBUF_DEFINE_DEFAULT_REPEATED(bool) + +#undef PROTOBUF_DEFINE_DEFAULT_REPEATED + +struct StaticDefaultRepeatedFieldsInitializer { + StaticDefaultRepeatedFieldsInitializer() { + InitializeDefaultRepeatedFields(); + } +} static_repeated_fields_initializer; + +void InitializeDefaultRepeatedFields() { + RepeatedStringTypeTraits::default_repeated_field_ = + new RepeatedStringTypeTraits::RepeatedFieldType; + RepeatedMessageGenericTypeTraits::default_repeated_field_ = + new RepeatedMessageGenericTypeTraits::RepeatedFieldType; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int32_ = + new RepeatedField; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int64_ = + new RepeatedField; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint32_ = + new RepeatedField; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint64_ = + new RepeatedField; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_double_ = + new RepeatedField; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_float_ = + new RepeatedField; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_bool_ = + new RepeatedField; +} + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index 14d5d15..ebe19e0 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -39,13 +39,15 @@ #define GOOGLE_PROTOBUF_EXTENSION_SET_H__ #include -#include #include #include #include + #include +#include + namespace google { namespace protobuf { @@ -62,10 +64,7 @@ namespace protobuf { } namespace internal { class FieldSkipper; // wire_format_lite.h - class RepeatedPtrFieldBase; // repeated_field.h } - template class RepeatedField; // repeated_field.h - template class RepeatedPtrField; // repeated_field.h } namespace protobuf { @@ -89,8 +88,8 @@ typedef bool EnumValidityFuncWithArg(const void* arg, int number); // Information about a registered extension. struct ExtensionInfo { inline ExtensionInfo() {} - inline ExtensionInfo(FieldType type, bool is_repeated, bool is_packed) - : type(type), is_repeated(is_repeated), is_packed(is_packed), + inline ExtensionInfo(FieldType type_param, bool isrepeated, bool ispacked) + : type(type_param), is_repeated(isrepeated), is_packed(ispacked), descriptor(NULL) {} FieldType type; @@ -138,6 +137,9 @@ class LIBPROTOBUF_EXPORT GeneratedExtensionFinder : public ExtensionFinder { const MessageLite* containing_type_; }; +// A FieldSkipper used for parsing MessageSet. +class MessageSetFieldSkipper; + // Note: extension_set_heavy.cc defines DescriptorPoolExtensionFinder for // finding extensions from a DescriptorPool. @@ -180,7 +182,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // is useful to implement Reflection::ListFields(). void AppendToList(const Descriptor* containing_type, const DescriptorPool* pool, - vector* output) const; + std::vector* output) const; // ================================================================= // Accessors @@ -214,6 +216,8 @@ class LIBPROTOBUF_EXPORT ExtensionSet { bool Has(int number) const; int ExtensionSize(int number) const; // Size of a repeated extension. + int NumExtensions() const; // The number of extensions + FieldType ExtensionType(int number) const; void ClearExtension(int number); // singular fields ------------------------------------------------- @@ -250,10 +254,35 @@ class LIBPROTOBUF_EXPORT ExtensionSet { const MessageLite& prototype, desc); MessageLite* MutableMessage(const FieldDescriptor* decsriptor, MessageFactory* factory); + // Adds the given message to the ExtensionSet, taking ownership of the + // message object. Existing message with the same number will be deleted. + // If "message" is NULL, this is equivalent to "ClearExtension(number)". + void SetAllocatedMessage(int number, FieldType type, + const FieldDescriptor* descriptor, + MessageLite* message); + MessageLite* ReleaseMessage(int number, const MessageLite& prototype); + MessageLite* ReleaseMessage(const FieldDescriptor* descriptor, + MessageFactory* factory); #undef desc // repeated fields ------------------------------------------------- + // Fetches a RepeatedField extension by number; returns |default_value| + // if no such extension exists. User should not touch this directly; it is + // used by the GetRepeatedExtension() method. + const void* GetRawRepeatedField(int number, const void* default_value) const; + // Fetches a mutable version of a RepeatedField extension by number, + // instantiating one if none exists. Similar to above, user should not use + // this directly; it underlies MutableRepeatedExtension(). + void* MutableRawRepeatedField(int number, FieldType field_type, + bool packed, const FieldDescriptor* desc); + + // This is an overload of MutableRawRepeatedField to maintain compatibility + // with old code using a previous API. This version of + // MutableRawRepeatedField() will GOOGLE_CHECK-fail on a missing extension. + // (E.g.: borg/clients/internal/proto1/proto2_reflection.cc.) + void* MutableRawRepeatedField(int number); + int32 GetRepeatedInt32 (int number, int index) const; int64 GetRepeatedInt64 (int number, int index) const; uint32 GetRepeatedUInt32(int number, int index) const; @@ -295,6 +324,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { #undef desc void RemoveLast(int number); + MessageLite* ReleaseLast(int number); void SwapElements(int number, int index1, int index2); // ----------------------------------------------------------------- @@ -309,31 +339,35 @@ class LIBPROTOBUF_EXPORT ExtensionSet { void Clear(); void MergeFrom(const ExtensionSet& other); void Swap(ExtensionSet* other); + void SwapExtension(ExtensionSet* other, int number); bool IsInitialized() const; - // Parses a single extension from the input. The input should start out - // positioned immediately after the tag. |containing_type| is the default - // instance for the containing message; it is used only to look up the - // extension by number. See RegisterExtension(), above. Unlike the other - // methods of ExtensionSet, this only works for generated message types -- - // it looks up extensions registered using RegisterExtension(). + // Parses a single extension from the input. The input should start out + // positioned immediately after the tag. bool ParseField(uint32 tag, io::CodedInputStream* input, ExtensionFinder* extension_finder, FieldSkipper* field_skipper); // Specific versions for lite or full messages (constructs the appropriate - // FieldSkipper automatically). + // FieldSkipper automatically). |containing_type| is the default + // instance for the containing message; it is used only to look up the + // extension by number. See RegisterExtension(), above. Unlike the other + // methods of ExtensionSet, this only works for generated message types -- + // it looks up extensions registered using RegisterExtension(). bool ParseField(uint32 tag, io::CodedInputStream* input, const MessageLite* containing_type); bool ParseField(uint32 tag, io::CodedInputStream* input, const Message* containing_type, UnknownFieldSet* unknown_fields); + bool ParseField(uint32 tag, io::CodedInputStream* input, + const MessageLite* containing_type, + io::CodedOutputStream* unknown_fields); // Parse an entire message in MessageSet format. Such messages have no // fields, only extensions. bool ParseMessageSet(io::CodedInputStream* input, ExtensionFinder* extension_finder, - FieldSkipper* field_skipper); + MessageSetFieldSkipper* field_skipper); // Specific versions for lite or full messages (constructs the appropriate // FieldSkipper automatically). @@ -381,18 +415,49 @@ class LIBPROTOBUF_EXPORT ExtensionSet { private: + // Interface of a lazily parsed singular message extension. + class LIBPROTOBUF_EXPORT LazyMessageExtension { + public: + LazyMessageExtension() {} + virtual ~LazyMessageExtension() {} + + virtual LazyMessageExtension* New() const = 0; + virtual const MessageLite& GetMessage( + const MessageLite& prototype) const = 0; + virtual MessageLite* MutableMessage(const MessageLite& prototype) = 0; + virtual void SetAllocatedMessage(MessageLite *message) = 0; + virtual MessageLite* ReleaseMessage(const MessageLite& prototype) = 0; + + virtual bool IsInitialized() const = 0; + virtual int ByteSize() const = 0; + virtual int SpaceUsed() const = 0; + + virtual void MergeFrom(const LazyMessageExtension& other) = 0; + virtual void Clear() = 0; + + virtual bool ReadMessage(const MessageLite& prototype, + io::CodedInputStream* input) = 0; + virtual void WriteMessage(int number, + io::CodedOutputStream* output) const = 0; + virtual uint8* WriteMessageToArray(int number, uint8* target) const = 0; + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyMessageExtension); + }; struct Extension { + // The order of these fields packs Extension into 24 bytes when using 8 + // byte alignment. Consider this when adding or removing fields here. union { - int32 int32_value; - int64 int64_value; - uint32 uint32_value; - uint64 uint64_value; - float float_value; - double double_value; - bool bool_value; - int enum_value; - string* string_value; - MessageLite* message_value; + int32 int32_value; + int64 int64_value; + uint32 uint32_value; + uint64 uint64_value; + float float_value; + double double_value; + bool bool_value; + int enum_value; + string* string_value; + MessageLite* message_value; + LazyMessageExtension* lazymessage_value; RepeatedField * repeated_int32_value; RepeatedField * repeated_int64_value; @@ -415,21 +480,28 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // removing it from the map, we just set is_cleared = true. This has no // meaning for repeated types; for those, the size of the RepeatedField // simply becomes zero when cleared. - bool is_cleared; + bool is_cleared : 4; + + // For singular message types, indicates whether lazy parsing is enabled + // for this extension. This field is only valid when type == TYPE_MESSAGE + // and !is_repeated because we only support lazy parsing for singular + // message types currently. If is_lazy = true, the extension is stored in + // lazymessage_value. Otherwise, the extension will be message_value. + bool is_lazy : 4; // For repeated types, this indicates if the [packed=true] option is set. bool is_packed; - // The descriptor for this extension, if one exists and is known. May be - // NULL. Must not be NULL if the descriptor for the extension does not - // live in the same pool as the descriptor for the containing type. - const FieldDescriptor* descriptor; - // For packed fields, the size of the packed data is recorded here when // ByteSize() is called then used during serialization. // TODO(kenton): Use atomic when C++ supports it. mutable int cached_size; + // The descriptor for this extension, if one exists and is known. May be + // NULL. Must not be NULL if the descriptor for the extension does not + // live in the same pool as the descriptor for the containing type. + const FieldDescriptor* descriptor; + // Some helper methods for operations on a single Extension. void SerializeFieldWithCachedSizes( int number, @@ -451,6 +523,41 @@ class LIBPROTOBUF_EXPORT ExtensionSet { int SpaceUsedExcludingSelf() const; }; + + // Returns true and fills field_number and extension if extension is found. + // Note to support packed repeated field compatibility, it also fills whether + // the tag on wire is packed, which can be different from + // extension->is_packed (whether packed=true is specified). + bool FindExtensionInfoFromTag(uint32 tag, ExtensionFinder* extension_finder, + int* field_number, ExtensionInfo* extension, + bool* was_packed_on_wire); + + // Returns true and fills extension if extension is found. + // Note to support packed repeated field compatibility, it also fills whether + // the tag on wire is packed, which can be different from + // extension->is_packed (whether packed=true is specified). + bool FindExtensionInfoFromFieldNumber(int wire_type, int field_number, + ExtensionFinder* extension_finder, + ExtensionInfo* extension, + bool* was_packed_on_wire); + + // Parses a single extension from the input. The input should start out + // positioned immediately after the wire tag. This method is called in + // ParseField() after field number and was_packed_on_wire is extracted from + // the wire tag and ExtensionInfo is found by the field number. + bool ParseFieldWithExtensionInfo(int field_number, + bool was_packed_on_wire, + const ExtensionInfo& extension, + io::CodedInputStream* input, + FieldSkipper* field_skipper); + + // Like ParseField(), but this method may parse singular message extensions + // lazily depending on the value of FLAGS_eagerly_parse_message_sets. + bool ParseFieldMaybeLazily(int wire_type, int field_number, + io::CodedInputStream* input, + ExtensionFinder* extension_finder, + MessageSetFieldSkipper* field_skipper); + // Gets the extension with the given number, creating it if it does not // already exist. Returns true if the extension did not already exist. bool MaybeNewExtension(int number, const FieldDescriptor* descriptor, @@ -460,7 +567,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // tag has been read. bool ParseMessageSetItem(io::CodedInputStream* input, ExtensionFinder* extension_finder, - FieldSkipper* field_skipper); + MessageSetFieldSkipper* field_skipper); // Hack: RepeatedPtrFieldBase declares ExtensionSet as a friend. This @@ -479,7 +586,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // only contain a small number of extensions whereas hash_map is optimized // for 100 elements or more. Also, we want AppendToList() to order fields // by field number. - map extensions_; + std::map extensions_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet); }; @@ -515,6 +622,16 @@ inline void ExtensionSet::AddString(int number, FieldType type, // public: // typedef ? ConstType; // typedef ? MutableType; +// // TypeTraits for singular fields and repeated fields will define the +// // symbol "Singular" or "Repeated" respectively. These two symbols will +// // be used in extension accessors to distinguish between singular +// // extensions and repeated extensions. If the TypeTraits for the passed +// // in extension doesn't have the expected symbol defined, it means the +// // user is passing a repeated extension to a singular accessor, or the +// // opposite. In that case the C++ compiler will generate an error +// // message "no matching member function" to inform the user. +// typedef ? Singular +// typedef ? Repeated // // static inline ConstType Get(int number, const ExtensionSet& set); // static inline void Set(int number, ConstType value, ExtensionSet* set); @@ -553,6 +670,8 @@ template class PrimitiveTypeTraits { public: typedef Type ConstType; + typedef Type MutableType; + typedef PrimitiveTypeTraits Singular; static inline ConstType Get(int number, const ExtensionSet& set, ConstType default_value); @@ -564,11 +683,39 @@ template class RepeatedPrimitiveTypeTraits { public: typedef Type ConstType; + typedef Type MutableType; + typedef RepeatedPrimitiveTypeTraits Repeated; + + typedef RepeatedField RepeatedFieldType; static inline Type Get(int number, const ExtensionSet& set, int index); static inline void Set(int number, int index, Type value, ExtensionSet* set); static inline void Add(int number, FieldType field_type, bool is_packed, Type value, ExtensionSet* set); + + static inline const RepeatedField& + GetRepeated(int number, const ExtensionSet& set); + static inline RepeatedField* + MutableRepeated(int number, FieldType field_type, + bool is_packed, ExtensionSet* set); + + static const RepeatedFieldType* GetDefaultRepeatedField(); +}; + +// Declared here so that this can be friended below. +void InitializeDefaultRepeatedFields(); + +class LIBPROTOBUF_EXPORT RepeatedPrimitiveGenericTypeTraits { + private: + template friend class RepeatedPrimitiveTypeTraits; + friend void InitializeDefaultRepeatedFields(); + static const RepeatedField* default_repeated_field_int32_; + static const RepeatedField* default_repeated_field_int64_; + static const RepeatedField* default_repeated_field_uint32_; + static const RepeatedField* default_repeated_field_uint64_; + static const RepeatedField* default_repeated_field_double_; + static const RepeatedField* default_repeated_field_float_; + static const RepeatedField* default_repeated_field_bool_; }; #define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \ @@ -593,6 +740,26 @@ template<> inline void RepeatedPrimitiveTypeTraits::Add( \ int number, FieldType field_type, bool is_packed, \ TYPE value, ExtensionSet* set) { \ set->Add##METHOD(number, field_type, is_packed, value, NULL); \ +} \ +template<> inline const RepeatedField* \ + RepeatedPrimitiveTypeTraits::GetDefaultRepeatedField() { \ + return RepeatedPrimitiveGenericTypeTraits:: \ + default_repeated_field_##TYPE##_; \ +} \ +template<> inline const RepeatedField& \ + RepeatedPrimitiveTypeTraits::GetRepeated(int number, \ + const ExtensionSet& set) { \ + return *reinterpret_cast*>( \ + set.GetRawRepeatedField( \ + number, GetDefaultRepeatedField())); \ +} \ +template<> inline RepeatedField* \ + RepeatedPrimitiveTypeTraits::MutableRepeated(int number, \ + FieldType field_type, \ + bool is_packed, \ + ExtensionSet* set) { \ + return reinterpret_cast*>( \ + set->MutableRawRepeatedField(number, field_type, is_packed, NULL)); \ } PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32, Int32) @@ -613,6 +780,7 @@ class LIBPROTOBUF_EXPORT StringTypeTraits { public: typedef const string& ConstType; typedef string* MutableType; + typedef StringTypeTraits Singular; static inline const string& Get(int number, const ExtensionSet& set, ConstType default_value) { @@ -632,6 +800,9 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits { public: typedef const string& ConstType; typedef string* MutableType; + typedef RepeatedStringTypeTraits Repeated; + + typedef RepeatedPtrField RepeatedFieldType; static inline const string& Get(int number, const ExtensionSet& set, int index) { @@ -653,6 +824,27 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits { ExtensionSet* set) { return set->AddString(number, field_type, NULL); } + static inline const RepeatedPtrField& + GetRepeated(int number, const ExtensionSet& set) { + return *reinterpret_cast*>( + set.GetRawRepeatedField(number, GetDefaultRepeatedField())); + } + + static inline RepeatedPtrField* + MutableRepeated(int number, FieldType field_type, + bool is_packed, ExtensionSet* set) { + return reinterpret_cast*>( + set->MutableRawRepeatedField(number, field_type, + is_packed, NULL)); + } + + static const RepeatedFieldType* GetDefaultRepeatedField() { + return default_repeated_field_; + } + + private: + friend void InitializeDefaultRepeatedFields(); + static const RepeatedFieldType *default_repeated_field_; }; // ------------------------------------------------------------------- @@ -664,6 +856,8 @@ template class EnumTypeTraits { public: typedef Type ConstType; + typedef Type MutableType; + typedef EnumTypeTraits Singular; static inline ConstType Get(int number, const ExtensionSet& set, ConstType default_value) { @@ -680,6 +874,10 @@ template class RepeatedEnumTypeTraits { public: typedef Type ConstType; + typedef Type MutableType; + typedef RepeatedEnumTypeTraits Repeated; + + typedef RepeatedField RepeatedFieldType; static inline ConstType Get(int number, const ExtensionSet& set, int index) { return static_cast(set.GetRepeatedEnum(number, index)); @@ -694,6 +892,35 @@ class RepeatedEnumTypeTraits { GOOGLE_DCHECK(IsValid(value)); set->AddEnum(number, field_type, is_packed, value, NULL); } + static inline const RepeatedField& GetRepeated(int number, + const ExtensionSet& + set) { + // Hack: the `Extension` struct stores a RepeatedField for enums. + // RepeatedField cannot implicitly convert to RepeatedField + // so we need to do some casting magic. See message.h for similar + // contortions for non-extension fields. + return *reinterpret_cast*>( + set.GetRawRepeatedField(number, GetDefaultRepeatedField())); + } + + static inline RepeatedField* MutableRepeated(int number, + FieldType field_type, + bool is_packed, + ExtensionSet* set) { + return reinterpret_cast*>( + set->MutableRawRepeatedField(number, field_type, is_packed, NULL)); + } + + static const RepeatedFieldType* GetDefaultRepeatedField() { + // Hack: as noted above, repeated enum fields are internally stored as a + // RepeatedField. We need to be able to instantiate global static + // objects to return as default (empty) repeated fields on non-existent + // extensions. We would not be able to know a-priori all of the enum types + // (values of |Type|) to instantiate all of these, so we just re-use int32's + // default repeated field object. + return reinterpret_cast*>( + RepeatedPrimitiveTypeTraits::GetDefaultRepeatedField()); + } }; // ------------------------------------------------------------------- @@ -707,6 +934,7 @@ class MessageTypeTraits { public: typedef const Type& ConstType; typedef Type* MutableType; + typedef MessageTypeTraits Singular; static inline ConstType Get(int number, const ExtensionSet& set, ConstType default_value) { @@ -718,13 +946,28 @@ class MessageTypeTraits { return static_cast( set->MutableMessage(number, field_type, Type::default_instance(), NULL)); } + static inline void SetAllocated(int number, FieldType field_type, + MutableType message, ExtensionSet* set) { + set->SetAllocatedMessage(number, field_type, NULL, message); + } + static inline MutableType Release(int number, FieldType /* field_type */, + ExtensionSet* set) { + return static_cast(set->ReleaseMessage( + number, Type::default_instance())); + } }; +// forward declaration +class RepeatedMessageGenericTypeTraits; + template class RepeatedMessageTypeTraits { public: typedef const Type& ConstType; typedef Type* MutableType; + typedef RepeatedMessageTypeTraits Repeated; + + typedef RepeatedPtrField RepeatedFieldType; static inline ConstType Get(int number, const ExtensionSet& set, int index) { return static_cast(set.GetRepeatedMessage(number, index)); @@ -737,8 +980,46 @@ class RepeatedMessageTypeTraits { return static_cast( set->AddMessage(number, field_type, Type::default_instance(), NULL)); } + static inline const RepeatedPtrField& GetRepeated(int number, + const ExtensionSet& + set) { + // See notes above in RepeatedEnumTypeTraits::GetRepeated(): same + // casting hack applies here, because a RepeatedPtrField + // cannot naturally become a RepeatedPtrType even though Type is + // presumably a message. google::protobuf::Message goes through similar contortions + // with a reinterpret_cast<>. + return *reinterpret_cast*>( + set.GetRawRepeatedField(number, GetDefaultRepeatedField())); + } + static inline RepeatedPtrField* MutableRepeated(int number, + FieldType field_type, + bool is_packed, + ExtensionSet* set) { + return reinterpret_cast*>( + set->MutableRawRepeatedField(number, field_type, is_packed, NULL)); + } + + static const RepeatedFieldType* GetDefaultRepeatedField(); }; +// This class exists only to hold a generic default empty repeated field for all +// message-type repeated field extensions. +class LIBPROTOBUF_EXPORT RepeatedMessageGenericTypeTraits { + public: + typedef RepeatedPtrField< ::google::protobuf::MessageLite*> RepeatedFieldType; + private: + template friend class RepeatedMessageTypeTraits; + friend void InitializeDefaultRepeatedFields(); + static const RepeatedFieldType* default_repeated_field_; +}; + +template inline + const typename RepeatedMessageTypeTraits::RepeatedFieldType* + RepeatedMessageTypeTraits::GetDefaultRepeatedField() { + return reinterpret_cast( + RepeatedMessageGenericTypeTraits::default_repeated_field_); +} + // ------------------------------------------------------------------- // ExtensionIdentifier @@ -785,114 +1066,161 @@ class ExtensionIdentifier { // causes problems if the class has a nested message or enum type with that // name and "_TypeTraits" is technically reserved for the C++ library since // it starts with an underscore followed by a capital letter. +// +// For similar reason, we use "_field_type" and "_is_packed" as parameter names +// below, so that "field_type" and "is_packed" can be used as field names. #define GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(CLASSNAME) \ /* Has, Size, Clear */ \ template \ + ::google::protobuf::internal::FieldType _field_type, \ + bool _is_packed> \ inline bool HasExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ return _extensions_.Has(id.number()); \ } \ \ template \ + ::google::protobuf::internal::FieldType _field_type, \ + bool _is_packed> \ inline void ClearExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ _extensions_.ClearExtension(id.number()); \ } \ \ template \ + ::google::protobuf::internal::FieldType _field_type, \ + bool _is_packed> \ inline int ExtensionSize( \ const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ return _extensions_.ExtensionSize(id.number()); \ } \ \ /* Singular accessors */ \ template \ - inline typename _proto_TypeTraits::ConstType GetExtension( \ + ::google::protobuf::internal::FieldType _field_type, \ + bool _is_packed> \ + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ return _proto_TypeTraits::Get(id.number(), _extensions_, \ id.default_value()); \ } \ \ template \ - inline typename _proto_TypeTraits::MutableType MutableExtension( \ + ::google::protobuf::internal::FieldType _field_type, \ + bool _is_packed> \ + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \ - return _proto_TypeTraits::Mutable(id.number(), field_type, &_extensions_);\ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ + return _proto_TypeTraits::Mutable(id.number(), _field_type, \ + &_extensions_); \ } \ \ template \ + ::google::protobuf::internal::FieldType _field_type, \ + bool _is_packed> \ inline void SetExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \ - typename _proto_TypeTraits::ConstType value) { \ - _proto_TypeTraits::Set(id.number(), field_type, value, &_extensions_); \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + typename _proto_TypeTraits::Singular::ConstType value) { \ + _proto_TypeTraits::Set(id.number(), _field_type, value, &_extensions_); \ + } \ + \ + template \ + inline void SetAllocatedExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + typename _proto_TypeTraits::Singular::MutableType value) { \ + _proto_TypeTraits::SetAllocated(id.number(), _field_type, \ + value, &_extensions_); \ + } \ + template \ + inline typename _proto_TypeTraits::Singular::MutableType ReleaseExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ + return _proto_TypeTraits::Release(id.number(), _field_type, \ + &_extensions_); \ } \ \ /* Repeated accessors */ \ template \ - inline typename _proto_TypeTraits::ConstType GetExtension( \ + ::google::protobuf::internal::FieldType _field_type, \ + bool _is_packed> \ + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ int index) const { \ return _proto_TypeTraits::Get(id.number(), _extensions_, index); \ } \ \ template \ - inline typename _proto_TypeTraits::MutableType MutableExtension( \ + ::google::protobuf::internal::FieldType _field_type, \ + bool _is_packed> \ + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ int index) { \ return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_); \ } \ \ template \ + ::google::protobuf::internal::FieldType _field_type, \ + bool _is_packed> \ inline void SetExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \ - int index, typename _proto_TypeTraits::ConstType value) { \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + int index, typename _proto_TypeTraits::Repeated::ConstType value) { \ _proto_TypeTraits::Set(id.number(), index, value, &_extensions_); \ } \ \ template \ - inline typename _proto_TypeTraits::MutableType AddExtension( \ + ::google::protobuf::internal::FieldType _field_type, \ + bool _is_packed> \ + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \ - return _proto_TypeTraits::Add(id.number(), field_type, &_extensions_); \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ + return _proto_TypeTraits::Add(id.number(), _field_type, &_extensions_); \ } \ \ template \ + ::google::protobuf::internal::FieldType _field_type, \ + bool _is_packed> \ inline void AddExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \ - typename _proto_TypeTraits::ConstType value) { \ - _proto_TypeTraits::Add(id.number(), field_type, is_packed, \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + typename _proto_TypeTraits::Repeated::ConstType value) { \ + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, \ value, &_extensions_); \ + } \ + \ + template \ + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& \ + GetRepeatedExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, \ + _is_packed>& id) const { \ + return _proto_TypeTraits::GetRepeated(id.number(), _extensions_); \ + } \ + \ + template \ + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* \ + MutableRepeatedExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, \ + _is_packed>& id) { \ + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, \ + _is_packed, &_extensions_); \ } } // namespace internal diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index 2721f15..1d971fd 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -35,17 +35,43 @@ // Contains methods defined in extension_set.h which cannot be part of the // lite library because they use descriptors or reflection. -#include +#include #include +#include #include #include #include #include namespace google { + namespace protobuf { namespace internal { +// A FieldSkipper used to store unknown MessageSet fields into UnknownFieldSet. +class MessageSetFieldSkipper + : public UnknownFieldSetFieldSkipper { + public: + explicit MessageSetFieldSkipper(UnknownFieldSet* unknown_fields) + : UnknownFieldSetFieldSkipper(unknown_fields) {} + virtual ~MessageSetFieldSkipper() {} + + virtual bool SkipMessageSetField(io::CodedInputStream* input, + int field_number); +}; +bool MessageSetFieldSkipper::SkipMessageSetField( + io::CodedInputStream* input, int field_number) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (unknown_fields_ == NULL) { + return input->Skip(length); + } else { + return input->ReadString( + unknown_fields_->AddLengthDelimited(field_number), length); + } +} + + // Implementation of ExtensionFinder which finds extensions in a given // DescriptorPool, using the given MessageFactory to construct sub-objects. // This class is implemented in extension_set_heavy.cc. @@ -67,7 +93,7 @@ class DescriptorPoolExtensionFinder : public ExtensionFinder { void ExtensionSet::AppendToList(const Descriptor* containing_type, const DescriptorPool* pool, - vector* output) const { + std::vector* output) const { for (map::const_iterator iter = extensions_.begin(); iter != extensions_.end(); ++iter) { bool has = false; @@ -103,6 +129,11 @@ inline FieldDescriptor::CppType cpp_type(FieldType type) { static_cast(type)); } +inline WireFormatLite::FieldType field_type(FieldType type) { + GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE); + return static_cast(type); +} + #define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \ : FieldDescriptor::LABEL_OPTIONAL, \ @@ -118,7 +149,12 @@ const MessageLite& ExtensionSet::GetMessage(int number, return *factory->GetPrototype(message_type); } else { GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); - return *iter->second.message_value; + if (iter->second.is_lazy) { + return iter->second.lazymessage_value->GetMessage( + *factory->GetPrototype(message_type)); + } else { + return *iter->second.message_value; + } } } @@ -132,13 +168,41 @@ MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor, extension->is_packed = false; const MessageLite* prototype = factory->GetPrototype(descriptor->message_type()); - GOOGLE_CHECK(prototype != NULL); + extension->is_lazy = false; extension->message_value = prototype->New(); + extension->is_cleared = false; + return extension->message_value; } else { GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + extension->is_cleared = false; + if (extension->is_lazy) { + return extension->lazymessage_value->MutableMessage( + *factory->GetPrototype(descriptor->message_type())); + } else { + return extension->message_value; + } + } +} + +MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, + MessageFactory* factory) { + map::iterator iter = extensions_.find(descriptor->number()); + if (iter == extensions_.end()) { + // Not present. Return NULL. + return NULL; + } else { + GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); + MessageLite* ret = NULL; + if (iter->second.is_lazy) { + ret = iter->second.lazymessage_value->ReleaseMessage( + *factory->GetPrototype(descriptor->message_type())); + delete iter->second.lazymessage_value; + } else { + ret = iter->second.message_value; + } + extensions_.erase(descriptor->number()); + return ret; } - extension->is_cleared = false; - return extension->message_value; } MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor, @@ -157,7 +221,7 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor, // RepeatedPtrField does not know how to Add() since it cannot // allocate an abstract object, so we have to be tricky. MessageLite* result = extension->repeated_message_value - ->AddFromCleared >(); + ->AddFromCleared >(); if (result == NULL) { const MessageLite* prototype; if (extension->repeated_message_value->size() == 0) { @@ -220,7 +284,7 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, const Message* containing_type, UnknownFieldSet* unknown_fields) { - UnknownFieldSetFieldSkipper skipper(unknown_fields); + MessageSetFieldSkipper skipper(unknown_fields); if (input->GetExtensionPool() == NULL) { GeneratedExtensionFinder finder(containing_type); return ParseMessageSet(input, &finder, &skipper); @@ -286,7 +350,11 @@ int ExtensionSet::Extension::SpaceUsedExcludingSelf() const { StringSpaceUsedExcludingSelf(*string_value); break; case FieldDescriptor::CPPTYPE_MESSAGE: - total_size += down_cast(message_value)->SpaceUsed(); + if (is_lazy) { + total_size += lazymessage_value->SpaceUsed(); + } else { + total_size += down_cast(message_value)->SpaceUsed(); + } break; default: // No extra storage costs for primitive types. @@ -419,8 +487,15 @@ uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray( HANDLE_TYPE( BYTES, Bytes, *string_value); HANDLE_TYPE( ENUM, Enum, enum_value); HANDLE_TYPE( GROUP, Group, *message_value); - HANDLE_TYPE( MESSAGE, Message, *message_value); #undef HANDLE_TYPE + case FieldDescriptor::TYPE_MESSAGE: + if (is_lazy) { + target = lazymessage_value->WriteMessageToArray(number, target); + } else { + target = WireFormatLite::WriteMessageToArray( + number, *message_value, target); + } + break; } } return target; @@ -444,14 +519,216 @@ uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray( target = WireFormatLite::WriteUInt32ToArray( WireFormatLite::kMessageSetTypeIdNumber, number, target); // Write message. - target = WireFormatLite::WriteMessageToArray( - WireFormatLite::kMessageSetMessageNumber, *message_value, target); + if (is_lazy) { + target = lazymessage_value->WriteMessageToArray( + WireFormatLite::kMessageSetMessageNumber, target); + } else { + target = WireFormatLite::WriteMessageToArray( + WireFormatLite::kMessageSetMessageNumber, *message_value, target); + } // End group. target = io::CodedOutputStream::WriteTagToArray( WireFormatLite::kMessageSetItemEndTag, target); return target; } + +bool ExtensionSet::ParseFieldMaybeLazily( + int wire_type, int field_number, io::CodedInputStream* input, + ExtensionFinder* extension_finder, + MessageSetFieldSkipper* field_skipper) { + return ParseField(WireFormatLite::MakeTag( + field_number, static_cast(wire_type)), + input, extension_finder, field_skipper); +} + +bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, + ExtensionFinder* extension_finder, + MessageSetFieldSkipper* field_skipper) { + while (true) { + const uint32 tag = input->ReadTag(); + switch (tag) { + case 0: + return true; + case WireFormatLite::kMessageSetItemStartTag: + if (!ParseMessageSetItem(input, extension_finder, field_skipper)) { + return false; + } + break; + default: + if (!ParseField(tag, input, extension_finder, field_skipper)) { + return false; + } + break; + } + } +} + +bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, + const MessageLite* containing_type) { + MessageSetFieldSkipper skipper(NULL); + GeneratedExtensionFinder finder(containing_type); + return ParseMessageSet(input, &finder, &skipper); +} + +bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input, + ExtensionFinder* extension_finder, + MessageSetFieldSkipper* field_skipper) { + // TODO(kenton): It would be nice to share code between this and + // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the + // differences would be hard to factor out. + + // This method parses a group which should contain two fields: + // required int32 type_id = 2; + // required data message = 3; + + uint32 last_type_id = 0; + + // If we see message data before the type_id, we'll append it to this so + // we can parse it later. + string message_data; + + while (true) { + const uint32 tag = input->ReadTag(); + if (tag == 0) return false; + + switch (tag) { + case WireFormatLite::kMessageSetTypeIdTag: { + uint32 type_id; + if (!input->ReadVarint32(&type_id)) return false; + last_type_id = type_id; + + if (!message_data.empty()) { + // We saw some message data before the type_id. Have to parse it + // now. + io::CodedInputStream sub_input( + reinterpret_cast(message_data.data()), + message_data.size()); + if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + last_type_id, &sub_input, + extension_finder, field_skipper)) { + return false; + } + message_data.clear(); + } + + break; + } + + case WireFormatLite::kMessageSetMessageTag: { + if (last_type_id == 0) { + // We haven't seen a type_id yet. Append this data to message_data. + string temp; + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->ReadString(&temp, length)) return false; + io::StringOutputStream output_stream(&message_data); + io::CodedOutputStream coded_output(&output_stream); + coded_output.WriteVarint32(length); + coded_output.WriteString(temp); + } else { + // Already saw type_id, so we can parse this directly. + if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + last_type_id, input, + extension_finder, field_skipper)) { + return false; + } + } + + break; + } + + case WireFormatLite::kMessageSetItemEndTag: { + return true; + } + + default: { + if (!field_skipper->SkipField(input, tag)) return false; + } + } + } +} + +void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes( + int number, + io::CodedOutputStream* output) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but serialize it the normal way. + SerializeFieldWithCachedSizes(number, output); + return; + } + + if (is_cleared) return; + + // Start group. + output->WriteTag(WireFormatLite::kMessageSetItemStartTag); + + // Write type ID. + WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber, + number, + output); + // Write message. + if (is_lazy) { + lazymessage_value->WriteMessage( + WireFormatLite::kMessageSetMessageNumber, output); + } else { + WireFormatLite::WriteMessageMaybeToArray( + WireFormatLite::kMessageSetMessageNumber, + *message_value, + output); + } + + // End group. + output->WriteTag(WireFormatLite::kMessageSetItemEndTag); +} + +int ExtensionSet::Extension::MessageSetItemByteSize(int number) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but compute the byte size for it the + // normal way. + return ByteSize(number); + } + + if (is_cleared) return 0; + + int our_size = WireFormatLite::kMessageSetItemTagsSize; + + // type_id + our_size += io::CodedOutputStream::VarintSize32(number); + + // message + int message_size = 0; + if (is_lazy) { + message_size = lazymessage_value->ByteSize(); + } else { + message_size = message_value->ByteSize(); + } + + our_size += io::CodedOutputStream::VarintSize32(message_size); + our_size += message_size; + + return our_size; +} + +void ExtensionSet::SerializeMessageSetWithCachedSizes( + io::CodedOutputStream* output) const { + for (map::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output); + } +} + +int ExtensionSet::MessageSetByteSize() const { + int total_size = 0; + + for (map::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + total_size += iter->second.MessageSetItemByteSize(iter->first); + } + + return total_size; +} + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc index 000f846..fb3746a 100644 --- a/src/google/protobuf/extension_set_unittest.cc +++ b/src/google/protobuf/extension_set_unittest.cc @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -46,9 +47,10 @@ #include #include #include -#include +#include namespace google { + namespace protobuf { namespace internal { namespace { @@ -140,23 +142,98 @@ TEST(ExtensionSetTest, ClearOneField) { TestUtil::ExpectAllExtensionsSet(message); } +TEST(ExtensionSetTest, SetAllocatedExtension) { + unittest::TestAllExtensions message; + EXPECT_FALSE(message.HasExtension( + unittest::optional_foreign_message_extension)); + // Add a extension using SetAllocatedExtension + unittest::ForeignMessage* foreign_message = new unittest::ForeignMessage(); + message.SetAllocatedExtension(unittest::optional_foreign_message_extension, + foreign_message); + EXPECT_TRUE(message.HasExtension( + unittest::optional_foreign_message_extension)); + EXPECT_EQ(foreign_message, + message.MutableExtension( + unittest::optional_foreign_message_extension)); + EXPECT_EQ(foreign_message, + &message.GetExtension( + unittest::optional_foreign_message_extension)); + + // SetAllocatedExtension should delete the previously existing extension. + // (We reply on unittest to check memory leaks for this case) + message.SetAllocatedExtension(unittest::optional_foreign_message_extension, + new unittest::ForeignMessage()); + + // SetAllocatedExtension with a NULL parameter is equivalent to ClearExtenion. + message.SetAllocatedExtension(unittest::optional_foreign_message_extension, + NULL); + EXPECT_FALSE(message.HasExtension( + unittest::optional_foreign_message_extension)); +} + +TEST(ExtensionSetTest, ReleaseExtension) { + unittest::TestMessageSet message; + EXPECT_FALSE(message.HasExtension( + unittest::TestMessageSetExtension1::message_set_extension)); + // Add a extension using SetAllocatedExtension + unittest::TestMessageSetExtension1* extension = + new unittest::TestMessageSetExtension1(); + message.SetAllocatedExtension( + unittest::TestMessageSetExtension1::message_set_extension, + extension); + EXPECT_TRUE(message.HasExtension( + unittest::TestMessageSetExtension1::message_set_extension)); + // Release the extension using ReleaseExtension + unittest::TestMessageSetExtension1* released_extension = + message.ReleaseExtension( + unittest::TestMessageSetExtension1::message_set_extension); + EXPECT_EQ(extension, released_extension); + EXPECT_FALSE(message.HasExtension( + unittest::TestMessageSetExtension1::message_set_extension)); + // ReleaseExtension will return the underlying object even after + // ClearExtension is called. + message.SetAllocatedExtension( + unittest::TestMessageSetExtension1::message_set_extension, + extension); + message.ClearExtension( + unittest::TestMessageSetExtension1::message_set_extension); + released_extension = message.ReleaseExtension( + unittest::TestMessageSetExtension1::message_set_extension); + EXPECT_TRUE(released_extension != NULL); + delete released_extension; +} + + TEST(ExtensionSetTest, CopyFrom) { unittest::TestAllExtensions message1, message2; - string data; TestUtil::SetAllExtensions(&message1); message2.CopyFrom(message1); TestUtil::ExpectAllExtensionsSet(message2); + message2.CopyFrom(message1); // exercise copy when fields already exist + TestUtil::ExpectAllExtensionsSet(message2); +} + +TEST(ExtensioSetTest, CopyFromPacked) { + unittest::TestPackedExtensions message1, message2; + + TestUtil::SetPackedExtensions(&message1); + message2.CopyFrom(message1); + TestUtil::ExpectPackedExtensionsSet(message2); + message2.CopyFrom(message1); // exercise copy when fields already exist + TestUtil::ExpectPackedExtensionsSet(message2); } TEST(ExtensionSetTest, CopyFromUpcasted) { unittest::TestAllExtensions message1, message2; - string data; const Message& upcasted_message = message1; TestUtil::SetAllExtensions(&message1); message2.CopyFrom(upcasted_message); TestUtil::ExpectAllExtensionsSet(message2); + // exercise copy when fields already exist + message2.CopyFrom(upcasted_message); + TestUtil::ExpectAllExtensionsSet(message2); } TEST(ExtensionSetTest, SwapWithEmpty) { @@ -179,6 +256,82 @@ TEST(ExtensionSetTest, SwapWithSelf) { TestUtil::ExpectAllExtensionsSet(message); } +TEST(ExtensionSetTest, SwapExtension) { + unittest::TestAllExtensions message1; + unittest::TestAllExtensions message2; + + TestUtil::SetAllExtensions(&message1); + vector fields; + + // Swap empty fields. + const Reflection* reflection = message1.GetReflection(); + reflection->SwapFields(&message1, &message2, fields); + TestUtil::ExpectAllExtensionsSet(message1); + TestUtil::ExpectExtensionsClear(message2); + + // Swap two extensions. + fields.push_back( + reflection->FindKnownExtensionByNumber(12)); + fields.push_back( + reflection->FindKnownExtensionByNumber(25)); + reflection->SwapFields(&message1, &message2, fields); + + EXPECT_TRUE(message1.HasExtension(unittest::optional_int32_extension)); + EXPECT_FALSE(message1.HasExtension(unittest::optional_double_extension)); + EXPECT_FALSE(message1.HasExtension(unittest::optional_cord_extension)); + + EXPECT_FALSE(message2.HasExtension(unittest::optional_int32_extension)); + EXPECT_TRUE(message2.HasExtension(unittest::optional_double_extension)); + EXPECT_TRUE(message2.HasExtension(unittest::optional_cord_extension)); +} + +TEST(ExtensionSetTest, SwapExtensionWithEmpty) { + unittest::TestAllExtensions message1; + unittest::TestAllExtensions message2; + unittest::TestAllExtensions message3; + + TestUtil::SetAllExtensions(&message3); + + const Reflection* reflection = message3.GetReflection(); + vector fields; + reflection->ListFields(message3, &fields); + + reflection->SwapFields(&message1, &message2, fields); + + TestUtil::ExpectExtensionsClear(message1); + TestUtil::ExpectExtensionsClear(message2); +} + +TEST(ExtensionSetTest, SwapExtensionBothFull) { + unittest::TestAllExtensions message1; + unittest::TestAllExtensions message2; + + TestUtil::SetAllExtensions(&message1); + TestUtil::SetAllExtensions(&message2); + + const Reflection* reflection = message1.GetReflection(); + vector fields; + reflection->ListFields(message1, &fields); + + reflection->SwapFields(&message1, &message2, fields); + + TestUtil::ExpectAllExtensionsSet(message1); + TestUtil::ExpectAllExtensionsSet(message2); +} + +TEST(ExtensionSetTest, SwapExtensionWithSelf) { + unittest::TestAllExtensions message1; + + TestUtil::SetAllExtensions(&message1); + + vector fields; + const Reflection* reflection = message1.GetReflection(); + reflection->ListFields(message1, &fields); + reflection->SwapFields(&message1, &message1, fields); + + TestUtil::ExpectAllExtensionsSet(message1); +} + TEST(ExtensionSetTest, SerializationToArray) { // Serialize as TestAllExtensions and parse as TestAllTypes to insure wire // compatibility of extensions. @@ -276,6 +429,7 @@ TEST(ExtensionSetTest, Parsing) { TestUtil::SetAllFields(&source); source.SerializeToString(&data); EXPECT_TRUE(destination.ParseFromString(data)); + TestUtil::SetOneofFields(&destination); TestUtil::ExpectAllExtensionsSet(destination); } @@ -291,6 +445,48 @@ TEST(ExtensionSetTest, PackedParsing) { TestUtil::ExpectPackedExtensionsSet(destination); } +TEST(ExtensionSetTest, PackedToUnpackedParsing) { + unittest::TestPackedTypes source; + unittest::TestUnpackedExtensions destination; + string data; + + TestUtil::SetPackedFields(&source); + source.SerializeToString(&data); + EXPECT_TRUE(destination.ParseFromString(data)); + TestUtil::ExpectUnpackedExtensionsSet(destination); + + // Reserialize + unittest::TestUnpackedTypes unpacked; + TestUtil::SetUnpackedFields(&unpacked); + EXPECT_TRUE(unpacked.SerializeAsString() == destination.SerializeAsString()); + + // Make sure we can add extensions. + destination.AddExtension(unittest::unpacked_int32_extension, 1); + destination.AddExtension(unittest::unpacked_enum_extension, + protobuf_unittest::FOREIGN_BAR); +} + +TEST(ExtensionSetTest, UnpackedToPackedParsing) { + unittest::TestUnpackedTypes source; + unittest::TestPackedExtensions destination; + string data; + + TestUtil::SetUnpackedFields(&source); + source.SerializeToString(&data); + EXPECT_TRUE(destination.ParseFromString(data)); + TestUtil::ExpectPackedExtensionsSet(destination); + + // Reserialize + unittest::TestPackedTypes packed; + TestUtil::SetPackedFields(&packed); + EXPECT_TRUE(packed.SerializeAsString() == destination.SerializeAsString()); + + // Make sure we can add extensions. + destination.AddExtension(unittest::packed_int32_extension, 1); + destination.AddExtension(unittest::packed_enum_extension, + protobuf_unittest::FOREIGN_BAR); +} + TEST(ExtensionSetTest, IsInitialized) { // Test that IsInitialized() returns false if required fields in nested // extensions are missing. @@ -418,7 +614,8 @@ TEST(ExtensionSetTest, SpaceUsedExcludingSelf) { for (int i = 0; i < 16; ++i) { \ message.AddExtension(unittest::repeated_##type##_extension, value); \ } \ - int expected_size = sizeof(cpptype) * 16 + empty_repeated_field_size; \ + int expected_size = sizeof(cpptype) * (16 - \ + kMinRepeatedFieldAllocationSize) + empty_repeated_field_size; \ EXPECT_EQ(expected_size, message.SpaceUsed()) << #type; \ } while (0) @@ -450,7 +647,8 @@ TEST(ExtensionSetTest, SpaceUsedExcludingSelf) { for (int i = 0; i < 16; ++i) { message.AddExtension(unittest::repeated_string_extension, value); } - min_expected_size += (sizeof(value) + value.size()) * 16; + min_expected_size += (sizeof(value) + value.size()) * + (16 - kMinRepeatedFieldAllocationSize); EXPECT_LE(min_expected_size, message.SpaceUsed()); } // Repeated messages @@ -465,12 +663,263 @@ TEST(ExtensionSetTest, SpaceUsedExcludingSelf) { message.AddExtension(unittest::repeated_foreign_message_extension)-> CopyFrom(prototype); } - min_expected_size += 16 * prototype.SpaceUsed(); + min_expected_size += + (16 - kMinRepeatedFieldAllocationSize) * prototype.SpaceUsed(); EXPECT_LE(min_expected_size, message.SpaceUsed()); } } -#ifdef GTEST_HAS_DEATH_TEST +// N.B.: We do not test range-based for here because we remain C++03 compatible. +template +inline T SumAllExtensions(const M& message, ID extension, T zero) { + T sum = zero; + typename RepeatedField::const_iterator iter = + message.GetRepeatedExtension(extension).begin(); + typename RepeatedField::const_iterator end = + message.GetRepeatedExtension(extension).end(); + for (; iter != end; ++iter) { + sum += *iter; + } + return sum; +} + +template +inline void IncAllExtensions(M* message, ID extension, + T val) { + typename RepeatedField::iterator iter = + message->MutableRepeatedExtension(extension)->begin(); + typename RepeatedField::iterator end = + message->MutableRepeatedExtension(extension)->end(); + for (; iter != end; ++iter) { + *iter += val; + } +} + +TEST(ExtensionSetTest, RepeatedFields) { + unittest::TestAllExtensions message; + + // Test empty repeated-field case (b/12926163) + ASSERT_EQ(0, message.GetRepeatedExtension( + unittest::repeated_int32_extension).size()); + ASSERT_EQ(0, message.GetRepeatedExtension( + unittest::repeated_nested_enum_extension).size()); + ASSERT_EQ(0, message.GetRepeatedExtension( + unittest::repeated_string_extension).size()); + ASSERT_EQ(0, message.GetRepeatedExtension( + unittest::repeated_nested_message_extension).size()); + + unittest::TestAllTypes::NestedMessage nested_message; + nested_message.set_bb(42); + unittest::TestAllTypes::NestedEnum nested_enum = + unittest::TestAllTypes::NestedEnum_MIN; + + for (int i = 0; i < 10; ++i) { + message.AddExtension(unittest::repeated_int32_extension, 1); + message.AddExtension(unittest::repeated_int64_extension, 2); + message.AddExtension(unittest::repeated_uint32_extension, 3); + message.AddExtension(unittest::repeated_uint64_extension, 4); + message.AddExtension(unittest::repeated_sint32_extension, 5); + message.AddExtension(unittest::repeated_sint64_extension, 6); + message.AddExtension(unittest::repeated_fixed32_extension, 7); + message.AddExtension(unittest::repeated_fixed64_extension, 8); + message.AddExtension(unittest::repeated_sfixed32_extension, 7); + message.AddExtension(unittest::repeated_sfixed64_extension, 8); + message.AddExtension(unittest::repeated_float_extension, 9.0); + message.AddExtension(unittest::repeated_double_extension, 10.0); + message.AddExtension(unittest::repeated_bool_extension, true); + message.AddExtension(unittest::repeated_nested_enum_extension, nested_enum); + message.AddExtension(unittest::repeated_string_extension, + ::std::string("test")); + message.AddExtension(unittest::repeated_bytes_extension, + ::std::string("test\xFF")); + message.AddExtension( + unittest::repeated_nested_message_extension)->CopyFrom(nested_message); + message.AddExtension(unittest::repeated_nested_enum_extension, + nested_enum); + } + + ASSERT_EQ(10, SumAllExtensions( + message, unittest::repeated_int32_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_int32_extension, 1); + ASSERT_EQ(20, SumAllExtensions( + message, unittest::repeated_int32_extension, 0)); + + ASSERT_EQ(20, SumAllExtensions( + message, unittest::repeated_int64_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_int64_extension, 1); + ASSERT_EQ(30, SumAllExtensions( + message, unittest::repeated_int64_extension, 0)); + + ASSERT_EQ(30, SumAllExtensions( + message, unittest::repeated_uint32_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_uint32_extension, 1); + ASSERT_EQ(40, SumAllExtensions( + message, unittest::repeated_uint32_extension, 0)); + + ASSERT_EQ(40, SumAllExtensions( + message, unittest::repeated_uint64_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_uint64_extension, 1); + ASSERT_EQ(50, SumAllExtensions( + message, unittest::repeated_uint64_extension, 0)); + + ASSERT_EQ(50, SumAllExtensions( + message, unittest::repeated_sint32_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_sint32_extension, 1); + ASSERT_EQ(60, SumAllExtensions( + message, unittest::repeated_sint32_extension, 0)); + + ASSERT_EQ(60, SumAllExtensions( + message, unittest::repeated_sint64_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_sint64_extension, 1); + ASSERT_EQ(70, SumAllExtensions( + message, unittest::repeated_sint64_extension, 0)); + + ASSERT_EQ(70, SumAllExtensions( + message, unittest::repeated_fixed32_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_fixed32_extension, 1); + ASSERT_EQ(80, SumAllExtensions( + message, unittest::repeated_fixed32_extension, 0)); + + ASSERT_EQ(80, SumAllExtensions( + message, unittest::repeated_fixed64_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_fixed64_extension, 1); + ASSERT_EQ(90, SumAllExtensions( + message, unittest::repeated_fixed64_extension, 0)); + + // Usually, floating-point arithmetic cannot be trusted to be exact, so it is + // a Bad Idea to assert equality in a test like this. However, we're dealing + // with integers with a small number of significant mantissa bits, so we + // should actually have exact precision here. + ASSERT_EQ(90, SumAllExtensions( + message, unittest::repeated_float_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_float_extension, 1); + ASSERT_EQ(100, SumAllExtensions( + message, unittest::repeated_float_extension, 0)); + + ASSERT_EQ(100, SumAllExtensions( + message, unittest::repeated_double_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_double_extension, 1); + ASSERT_EQ(110, SumAllExtensions( + message, unittest::repeated_double_extension, 0)); + + RepeatedPtrField< ::std::string>::iterator string_iter; + RepeatedPtrField< ::std::string>::iterator string_end; + for (string_iter = message.MutableRepeatedExtension( + unittest::repeated_string_extension)->begin(), + string_end = message.MutableRepeatedExtension( + unittest::repeated_string_extension)->end(); + string_iter != string_end; ++string_iter) { + *string_iter += "test"; + } + RepeatedPtrField< ::std::string>::const_iterator string_const_iter; + RepeatedPtrField< ::std::string>::const_iterator string_const_end; + for (string_const_iter = message.GetRepeatedExtension( + unittest::repeated_string_extension).begin(), + string_const_end = message.GetRepeatedExtension( + unittest::repeated_string_extension).end(); + string_iter != string_end; ++string_iter) { + ASSERT_TRUE(*string_iter == "testtest"); + } + + RepeatedField::iterator enum_iter; + RepeatedField::iterator enum_end; + for (enum_iter = message.MutableRepeatedExtension( + unittest::repeated_nested_enum_extension)->begin(), + enum_end = message.MutableRepeatedExtension( + unittest::repeated_nested_enum_extension)->end(); + enum_iter != enum_end; ++enum_iter) { + *enum_iter = unittest::TestAllTypes::NestedEnum_MAX; + } + RepeatedField::const_iterator + enum_const_iter; + RepeatedField::const_iterator + enum_const_end; + for (enum_const_iter = message.GetRepeatedExtension( + unittest::repeated_nested_enum_extension).begin(), + enum_const_end = message.GetRepeatedExtension( + unittest::repeated_nested_enum_extension).end(); + enum_iter != enum_end; ++enum_iter) { + ASSERT_EQ(*enum_const_iter, unittest::TestAllTypes::NestedEnum_MAX); + } + + RepeatedPtrField::iterator + msg_iter; + RepeatedPtrField::iterator + msg_end; + for (msg_iter = message.MutableRepeatedExtension( + unittest::repeated_nested_message_extension)->begin(), + msg_end = message.MutableRepeatedExtension( + unittest::repeated_nested_message_extension)->end(); + msg_iter != msg_end; ++msg_iter) { + msg_iter->set_bb(1234); + } + RepeatedPtrField:: + const_iterator msg_const_iter; + RepeatedPtrField:: + const_iterator msg_const_end; + for (msg_const_iter = message.GetRepeatedExtension( + unittest::repeated_nested_message_extension).begin(), + msg_const_end = message.GetRepeatedExtension( + unittest::repeated_nested_message_extension).end(); + msg_const_iter != msg_const_end; ++msg_const_iter) { + ASSERT_EQ(msg_const_iter->bb(), 1234); + } + + // Test range-based for as well, but only if compiled as C++11. +#if __cplusplus >= 201103L + // Test one primitive field. + for (auto& x : *message.MutableRepeatedExtension( + unittest::repeated_int32_extension)) { + x = 4321; + } + for (const auto& x : message.GetRepeatedExtension( + unittest::repeated_int32_extension)) { + ASSERT_EQ(x, 4321); + } + // Test one string field. + for (auto& x : *message.MutableRepeatedExtension( + unittest::repeated_string_extension)) { + x = "test_range_based_for"; + } + for (const auto& x : message.GetRepeatedExtension( + unittest::repeated_string_extension)) { + ASSERT_TRUE(x == "test_range_based_for"); + } + // Test one message field. + for (auto& x : *message.MutableRepeatedExtension( + unittest::repeated_nested_message_extension)) { + x.set_bb(4321); + } + for (const auto& x : *message.MutableRepeatedExtension( + unittest::repeated_nested_message_extension)) { + ASSERT_EQ(x.bb(), 4321); + } +#endif +} + +// From b/12926163 +TEST(ExtensionSetTest, AbsentExtension) { + unittest::TestAllExtensions message; + message.MutableRepeatedExtension(unittest::repeated_nested_message_extension) + ->Add()->set_bb(123); + ASSERT_EQ(1, message.ExtensionSize( + unittest::repeated_nested_message_extension)); + EXPECT_EQ( + 123, message.GetExtension( + unittest::repeated_nested_message_extension, 0).bb()); +} + +#ifdef PROTOBUF_HAS_DEATH_TEST TEST(ExtensionSetTest, InvalidEnumDeath) { unittest::TestAllExtensions message; @@ -480,7 +929,7 @@ TEST(ExtensionSetTest, InvalidEnumDeath) { "IsValid"); } -#endif // GTEST_HAS_DEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST TEST(ExtensionSetTest, DynamicExtensions) { // Test adding a dynamic extension to a compiled-in message object. @@ -615,7 +1064,11 @@ TEST(ExtensionSetTest, DynamicExtensions) { const Message& sub_message = message.GetReflection()->GetMessage(message, message_extension); const unittest::ForeignMessage* typed_sub_message = +#ifdef GOOGLE_PROTOBUF_NO_RTTI + static_cast(&sub_message); +#else dynamic_cast(&sub_message); +#endif ASSERT_TRUE(typed_sub_message != NULL); EXPECT_EQ(456, typed_sub_message->c()); } diff --git a/src/google/protobuf/generated_enum_reflection.h b/src/google/protobuf/generated_enum_reflection.h new file mode 100644 index 0000000..2780a9b --- /dev/null +++ b/src/google/protobuf/generated_enum_reflection.h @@ -0,0 +1,91 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: jasonh@google.com (Jason Hsueh) +// +// This header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. +// It provides reflection support for generated enums, and is included in +// generated .pb.h files and should have minimal dependencies. The methods are +// implemented in generated_message_reflection.cc. + +#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ +#define GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ + +#include + +#include + +namespace google { +namespace protobuf { + class EnumDescriptor; +} // namespace protobuf + +namespace protobuf { + +// This type trait can be used to cause templates to only match proto2 enum +// types. +template struct is_proto_enum : ::google::protobuf::internal::false_type {}; + +// Returns the EnumDescriptor for enum type E, which must be a +// proto-declared enum type. Code generated by the protocol compiler +// will include specializations of this template for each enum type declared. +template +const EnumDescriptor* GetEnumDescriptor(); + +namespace internal { + +// Helper for EnumType_Parse functions: try to parse the string 'name' as an +// enum name of the given type, returning true and filling in value on success, +// or returning false and leaving value unchanged on failure. +LIBPROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor, + const string& name, + int* value); + +template +bool ParseNamedEnum(const EnumDescriptor* descriptor, + const string& name, + EnumType* value) { + int tmp; + if (!ParseNamedEnum(descriptor, name, &tmp)) return false; + *value = static_cast(tmp); + return true; +} + +// Just a wrapper around printing the name of a value. The main point of this +// function is not to be inlined, so that you can do this without including +// descriptor.h. +LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value); + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 0f065ff..7cfaa98 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -33,25 +33,26 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include +#include #include #include -#include #include #include #include #include +#define GOOGLE_PROTOBUF_HAS_ONEOF + namespace google { namespace protobuf { namespace internal { -namespace { const string kEmptyString; } - int StringSpaceUsedExcludingSelf(const string& str) { const void* start = &str; const void* end = &str + 1; - if (start <= str.data() && str.data() <= end) { + if (start <= str.data() && str.data() < end) { // The string's data is stored inside the string object itself. return 0; } else { @@ -69,9 +70,8 @@ bool ParseNamedEnum(const EnumDescriptor* descriptor, } const string& NameOfEnum(const EnumDescriptor* descriptor, int value) { - static string kEmptyString; const EnumValueDescriptor* d = descriptor->FindValueByNumber(value); - return (d == NULL ? kEmptyString : d->name()); + return (d == NULL ? GetEmptyString() : d->name()); } // =================================================================== @@ -191,6 +191,33 @@ GeneratedMessageReflection::GeneratedMessageReflection( message_factory_ (factory) { } +GeneratedMessageReflection::GeneratedMessageReflection( + const Descriptor* descriptor, + const Message* default_instance, + const int offsets[], + int has_bits_offset, + int unknown_fields_offset, + int extensions_offset, + const void* default_oneof_instance, + int oneof_case_offset, + const DescriptorPool* descriptor_pool, + MessageFactory* factory, + int object_size) + : descriptor_ (descriptor), + default_instance_ (default_instance), + default_oneof_instance_ (default_oneof_instance), + offsets_ (offsets), + has_bits_offset_ (has_bits_offset), + oneof_case_offset_(oneof_case_offset), + unknown_fields_offset_(unknown_fields_offset), + extensions_offset_(extensions_offset), + object_size_ (object_size), + descriptor_pool_ ((descriptor_pool == NULL) ? + DescriptorPool::generated_pool() : + descriptor_pool), + message_factory_ (factory) { +} + GeneratedMessageReflection::~GeneratedMessageReflection() {} const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields( @@ -257,6 +284,9 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const { break; } } else { + if (field->containing_oneof() && !HasOneofField(message, field)) { + continue; + } switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32 : case FieldDescriptor::CPPTYPE_INT64 : @@ -309,6 +339,195 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const { return total_size; } +void GeneratedMessageReflection::SwapField( + Message* message1, + Message* message2, + const FieldDescriptor* field) const { + if (field->is_repeated()) { + switch (field->cpp_type()) { +#define SWAP_ARRAYS(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + MutableRaw >(message1, field)->Swap( \ + MutableRaw >(message2, field)); \ + break; + + SWAP_ARRAYS(INT32 , int32 ); + SWAP_ARRAYS(INT64 , int64 ); + SWAP_ARRAYS(UINT32, uint32); + SWAP_ARRAYS(UINT64, uint64); + SWAP_ARRAYS(FLOAT , float ); + SWAP_ARRAYS(DOUBLE, double); + SWAP_ARRAYS(BOOL , bool ); + SWAP_ARRAYS(ENUM , int ); +#undef SWAP_ARRAYS + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + MutableRaw(message1, field)->Swap( + MutableRaw(message2, field)); + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); + } + } else { + switch (field->cpp_type()) { +#define SWAP_VALUES(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + std::swap(*MutableRaw(message1, field), \ + *MutableRaw(message2, field)); \ + break; + + SWAP_VALUES(INT32 , int32 ); + SWAP_VALUES(INT64 , int64 ); + SWAP_VALUES(UINT32, uint32); + SWAP_VALUES(UINT64, uint64); + SWAP_VALUES(FLOAT , float ); + SWAP_VALUES(DOUBLE, double); + SWAP_VALUES(BOOL , bool ); + SWAP_VALUES(ENUM , int ); +#undef SWAP_VALUES + case FieldDescriptor::CPPTYPE_MESSAGE: + std::swap(*MutableRaw(message1, field), + *MutableRaw(message2, field)); + break; + + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + std::swap(*MutableRaw(message1, field), + *MutableRaw(message2, field)); + break; + } + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); + } + } +} + +void GeneratedMessageReflection::SwapOneofField( + Message* message1, + Message* message2, + const OneofDescriptor* oneof_descriptor) const { + uint32 oneof_case1 = GetOneofCase(*message1, oneof_descriptor); + uint32 oneof_case2 = GetOneofCase(*message2, oneof_descriptor); + + int32 temp_int32; + int64 temp_int64; + uint32 temp_uint32; + uint64 temp_uint64; + float temp_float; + double temp_double; + bool temp_bool; + int temp_int; + Message* temp_message; + string temp_string; + + // Stores message1's oneof field to a temp variable. + const FieldDescriptor* field1; + if (oneof_case1 > 0) { + field1 = descriptor_->FindFieldByNumber(oneof_case1); + //oneof_descriptor->field(oneof_case1); + switch (field1->cpp_type()) { +#define GET_TEMP_VALUE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + temp_##TYPE = GetField(*message1, field1); \ + break; + + GET_TEMP_VALUE(INT32 , int32 ); + GET_TEMP_VALUE(INT64 , int64 ); + GET_TEMP_VALUE(UINT32, uint32); + GET_TEMP_VALUE(UINT64, uint64); + GET_TEMP_VALUE(FLOAT , float ); + GET_TEMP_VALUE(DOUBLE, double); + GET_TEMP_VALUE(BOOL , bool ); + GET_TEMP_VALUE(ENUM , int ); +#undef GET_TEMP_VALUE + case FieldDescriptor::CPPTYPE_MESSAGE: + temp_message = ReleaseMessage(message1, field1); + break; + + case FieldDescriptor::CPPTYPE_STRING: + temp_string = GetString(*message1, field1); + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field1->cpp_type(); + } + } + + // Sets message1's oneof field from the message2's oneof field. + if (oneof_case2 > 0) { + const FieldDescriptor* field2 = + descriptor_->FindFieldByNumber(oneof_case2); + switch (field2->cpp_type()) { +#define SET_ONEOF_VALUE1(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + SetField(message1, field2, GetField(*message2, field2)); \ + break; + + SET_ONEOF_VALUE1(INT32 , int32 ); + SET_ONEOF_VALUE1(INT64 , int64 ); + SET_ONEOF_VALUE1(UINT32, uint32); + SET_ONEOF_VALUE1(UINT64, uint64); + SET_ONEOF_VALUE1(FLOAT , float ); + SET_ONEOF_VALUE1(DOUBLE, double); + SET_ONEOF_VALUE1(BOOL , bool ); + SET_ONEOF_VALUE1(ENUM , int ); +#undef SET_ONEOF_VALUE1 + case FieldDescriptor::CPPTYPE_MESSAGE: + SetAllocatedMessage(message1, + ReleaseMessage(message2, field2), + field2); + break; + + case FieldDescriptor::CPPTYPE_STRING: + SetString(message1, field2, GetString(*message2, field2)); + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field2->cpp_type(); + } + } else { + ClearOneof(message1, oneof_descriptor); + } + + // Sets message2's oneof field from the temp variable. + if (oneof_case1 > 0) { + switch (field1->cpp_type()) { +#define SET_ONEOF_VALUE2(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + SetField(message2, field1, temp_##TYPE); \ + break; + + SET_ONEOF_VALUE2(INT32 , int32 ); + SET_ONEOF_VALUE2(INT64 , int64 ); + SET_ONEOF_VALUE2(UINT32, uint32); + SET_ONEOF_VALUE2(UINT64, uint64); + SET_ONEOF_VALUE2(FLOAT , float ); + SET_ONEOF_VALUE2(DOUBLE, double); + SET_ONEOF_VALUE2(BOOL , bool ); + SET_ONEOF_VALUE2(ENUM , int ); +#undef SET_ONEOF_VALUE2 + case FieldDescriptor::CPPTYPE_MESSAGE: + SetAllocatedMessage(message2, temp_message, field1); + break; + + case FieldDescriptor::CPPTYPE_STRING: + SetString(message2, field1, temp_string); + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field1->cpp_type(); + } + } else { + ClearOneof(message2, oneof_descriptor); + } +} + void GeneratedMessageReflection::Swap( Message* message1, Message* message2) const { @@ -324,7 +543,7 @@ void GeneratedMessageReflection::Swap( "descriptor."; GOOGLE_CHECK_EQ(message2->GetReflection(), this) << "Second argument to Swap() (of type \"" - << message1->GetDescriptor()->full_name() + << message2->GetDescriptor()->full_name() << "\") is not compatible with this reflection object (which is for type \"" << descriptor_->full_name() << "\"). Note that the exact same class is required; not just the same " @@ -340,73 +559,69 @@ void GeneratedMessageReflection::Swap( for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (field->is_repeated()) { - switch (field->cpp_type()) { -#define SWAP_ARRAYS(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - MutableRaw >(message1, field)->Swap( \ - MutableRaw >(message2, field)); \ - break; + if (!field->containing_oneof()) { + SwapField(message1, message2, field); + } + } - SWAP_ARRAYS(INT32 , int32 ); - SWAP_ARRAYS(INT64 , int64 ); - SWAP_ARRAYS(UINT32, uint32); - SWAP_ARRAYS(UINT64, uint64); - SWAP_ARRAYS(FLOAT , float ); - SWAP_ARRAYS(DOUBLE, double); - SWAP_ARRAYS(BOOL , bool ); - SWAP_ARRAYS(ENUM , int ); -#undef SWAP_ARRAYS + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + SwapOneofField(message1, message2, descriptor_->oneof_decl(i)); + } - case FieldDescriptor::CPPTYPE_STRING: - case FieldDescriptor::CPPTYPE_MESSAGE: - MutableRaw(message1, field)->Swap( - MutableRaw(message2, field)); - break; + if (extensions_offset_ != -1) { + MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2)); + } - default: - GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); - } - } else { - switch (field->cpp_type()) { -#define SWAP_VALUES(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - std::swap(*MutableRaw(message1, field), \ - *MutableRaw(message2, field)); \ - break; + MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2)); +} - SWAP_VALUES(INT32 , int32 ); - SWAP_VALUES(INT64 , int64 ); - SWAP_VALUES(UINT32, uint32); - SWAP_VALUES(UINT64, uint64); - SWAP_VALUES(FLOAT , float ); - SWAP_VALUES(DOUBLE, double); - SWAP_VALUES(BOOL , bool ); - SWAP_VALUES(ENUM , int ); - SWAP_VALUES(MESSAGE, Message*); -#undef SWAP_VALUES +void GeneratedMessageReflection::SwapFields( + Message* message1, + Message* message2, + const vector& fields) const { + if (message1 == message2) return; - case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // TODO(kenton): Support other string reps. - case FieldOptions::STRING: - std::swap(*MutableRaw(message1, field), - *MutableRaw(message2, field)); - break; - } - break; + // TODO(kenton): Other Reflection methods should probably check this too. + GOOGLE_CHECK_EQ(message1->GetReflection(), this) + << "First argument to SwapFields() (of type \"" + << message1->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type \"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; + GOOGLE_CHECK_EQ(message2->GetReflection(), this) + << "Second argument to SwapFields() (of type \"" + << message2->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type \"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; - default: - GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); + std::set swapped_oneof; + + for (int i = 0; i < fields.size(); i++) { + const FieldDescriptor* field = fields[i]; + if (field->is_extension()) { + MutableExtensionSet(message1)->SwapExtension( + MutableExtensionSet(message2), + field->number()); + } else { + if (field->containing_oneof()) { + int oneof_index = field->containing_oneof()->index(); + // Only swap the oneof field once. + if (swapped_oneof.find(oneof_index) != swapped_oneof.end()) { + continue; + } + swapped_oneof.insert(oneof_index); + SwapOneofField(message1, message2, field->containing_oneof()); + } else { + // Swap has bit. + SwapBit(message1, message2, field); + // Swap field. + SwapField(message1, message2, field); } } } - - if (extensions_offset_ != -1) { - MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2)); - } - - MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2)); } // ------------------------------------------------------------------- @@ -419,7 +634,11 @@ bool GeneratedMessageReflection::HasField(const Message& message, if (field->is_extension()) { return GetExtensionSet(message).Has(field->number()); } else { - return HasBit(message, field); + if (field->containing_oneof()) { + return HasOneofField(message, field); + } else { + return HasBit(message, field); + } } } @@ -463,6 +682,11 @@ void GeneratedMessageReflection::ClearField( if (field->is_extension()) { MutableExtensionSet(message)->ClearExtension(field->number()); } else if (!field->is_repeated()) { + if (field->containing_oneof()) { + ClearOneofField(message, field); + return; + } + if (HasBit(*message, field)) { ClearBit(message, field); @@ -591,6 +815,20 @@ void GeneratedMessageReflection::RemoveLast( } } +Message* GeneratedMessageReflection::ReleaseLast( + Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE); + + if (field->is_extension()) { + return static_cast( + MutableExtensionSet(message)->ReleaseLast(field->number())); + } else { + return MutableRaw(message, field) + ->ReleaseLast >(); + } +} + void GeneratedMessageReflection::SwapElements( Message* message, const FieldDescriptor* field, @@ -653,7 +891,11 @@ void GeneratedMessageReflection::ListFields( output->push_back(field); } } else { - if (HasBit(message, field)) { + if (field->containing_oneof()) { + if (HasOneofField(message, field)) { + output->push_back(field); + } + } else if (HasBit(message, field)) { output->push_back(field); } } @@ -757,7 +999,7 @@ string GeneratedMessageReflection::GetString( } GOOGLE_LOG(FATAL) << "Can't get here."; - return kEmptyString; // Make compiler happy. + return GetEmptyString(); // Make compiler happy. } } @@ -776,7 +1018,7 @@ const string& GeneratedMessageReflection::GetStringReference( } GOOGLE_LOG(FATAL) << "Can't get here."; - return kEmptyString; // Make compiler happy. + return GetEmptyString(); // Make compiler happy. } } @@ -792,6 +1034,10 @@ void GeneratedMessageReflection::SetString( switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { + if (field->containing_oneof() && !HasOneofField(*message, field)) { + ClearOneof(message, field->containing_oneof()); + *MutableField(message, field) = new string; + } string** ptr = MutableField(message, field); if (*ptr == DefaultRaw(field)) { *ptr = new string(value); @@ -818,7 +1064,7 @@ string GeneratedMessageReflection::GetRepeatedString( } GOOGLE_LOG(FATAL) << "Can't get here."; - return kEmptyString; // Make compiler happy. + return GetEmptyString(); // Make compiler happy. } } @@ -836,7 +1082,7 @@ const string& GeneratedMessageReflection::GetRepeatedStringReference( } GOOGLE_LOG(FATAL) << "Can't get here."; - return kEmptyString; // Make compiler happy. + return GetEmptyString(); // Make compiler happy. } } @@ -892,7 +1138,9 @@ const EnumValueDescriptor* GeneratedMessageReflection::GetEnum( } const EnumValueDescriptor* result = field->enum_type()->FindValueByNumber(value); - GOOGLE_CHECK(result != NULL); + GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field " + << field->full_name() << " of type " + << field->enum_type()->full_name() << "."; return result; } @@ -922,7 +1170,9 @@ const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum( } const EnumValueDescriptor* result = field->enum_type()->FindValueByNumber(value); - GOOGLE_CHECK(result != NULL); + GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field " + << field->full_name() << " of type " + << field->enum_type()->full_name() << "."; return result; } @@ -963,13 +1213,15 @@ const Message& GeneratedMessageReflection::GetMessage( MessageFactory* factory) const { USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE); + if (factory == NULL) factory = message_factory_; + if (field->is_extension()) { return static_cast( GetExtensionSet(message).GetMessage( - field->number(), field->message_type(), - factory == NULL ? message_factory_ : factory)); + field->number(), field->message_type(), factory)); } else { - const Message* result = GetRaw(message, field); + const Message* result; + result = GetRaw(message, field); if (result == NULL) { result = DefaultRaw(field); } @@ -980,19 +1232,91 @@ const Message& GeneratedMessageReflection::GetMessage( Message* GeneratedMessageReflection::MutableMessage( Message* message, const FieldDescriptor* field, MessageFactory* factory) const { - USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE); + if (factory == NULL) factory = message_factory_; if (field->is_extension()) { return static_cast( - MutableExtensionSet(message)->MutableMessage(field, - factory == NULL ? message_factory_ : factory)); + MutableExtensionSet(message)->MutableMessage(field, factory)); } else { - Message** result = MutableField(message, field); - if (*result == NULL) { + Message* result; + Message** result_holder = MutableRaw(message, field); + + if (field->containing_oneof()) { + if (!HasOneofField(*message, field)) { + ClearOneof(message, field->containing_oneof()); + result_holder = MutableField(message, field); + const Message* default_message = DefaultRaw(field); + *result_holder = default_message->New(); + } + } else { + SetBit(message, field); + } + + if (*result_holder == NULL) { const Message* default_message = DefaultRaw(field); - *result = default_message->New(); + *result_holder = default_message->New(); } - return *result; + result = *result_holder; + return result; + } +} + +void GeneratedMessageReflection::SetAllocatedMessage( + Message* message, + Message* sub_message, + const FieldDescriptor* field) const { + USAGE_CHECK_ALL(SetAllocatedMessage, SINGULAR, MESSAGE); + + if (field->is_extension()) { + MutableExtensionSet(message)->SetAllocatedMessage( + field->number(), field->type(), field, sub_message); + } else { + if (field->containing_oneof()) { + if (sub_message == NULL) { + ClearOneof(message, field->containing_oneof()); + return; + } + ClearOneof(message, field->containing_oneof()); + *MutableRaw(message, field) = sub_message; + SetOneofCase(message, field); + return; + } + + if (sub_message == NULL) { + ClearBit(message, field); + } else { + SetBit(message, field); + } + Message** sub_message_holder = MutableRaw(message, field); + delete *sub_message_holder; + *sub_message_holder = sub_message; + } +} + +Message* GeneratedMessageReflection::ReleaseMessage( + Message* message, + const FieldDescriptor* field, + MessageFactory* factory) const { + USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE); + + if (factory == NULL) factory = message_factory_; + + if (field->is_extension()) { + return static_cast( + MutableExtensionSet(message)->ReleaseMessage(field, factory)); + } else { + ClearBit(message, field); + if (field->containing_oneof()) { + if (HasOneofField(*message, field)) { + *MutableOneofCase(message, field->containing_oneof()) = 0; + } else { + return NULL; + } + } + Message** result = MutableRaw(message, field); + Message* ret = *result; + *result = NULL; + return ret; } } @@ -1037,7 +1361,7 @@ Message* GeneratedMessageReflection::AddMessage( // We can't use AddField() because RepeatedPtrFieldBase doesn't // know how to allocate one. RepeatedPtrFieldBase* repeated = - MutableRaw(message, field); + MutableRaw(message, field); Message* result = repeated->AddFromCleared >(); if (result == NULL) { // We must allocate a new object. @@ -1054,7 +1378,36 @@ Message* GeneratedMessageReflection::AddMessage( } } -// ------------------------------------------------------------------- +void* GeneratedMessageReflection::MutableRawRepeatedField( + Message* message, const FieldDescriptor* field, + FieldDescriptor::CppType cpptype, + int ctype, const Descriptor* desc) const { + USAGE_CHECK_REPEATED("MutableRawRepeatedField"); + if (field->cpp_type() != cpptype) + ReportReflectionUsageTypeError(descriptor_, + field, "MutableRawRepeatedField", cpptype); + if (ctype >= 0) + GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch"; + if (desc != NULL) + GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type"; + if (field->is_extension()) + return MutableExtensionSet(message)->MutableRawRepeatedField( + field->number(), field->type(), field->is_packed(), field); + else + return reinterpret_cast(message) + offsets_[field->index()]; +} + +const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor( + const Message& message, + const OneofDescriptor* oneof_descriptor) const { + uint32 field_number = GetOneofCase(message, oneof_descriptor); + if (field_number == 0) { + return NULL; + } + return descriptor_->FindFieldByNumber(field_number); +} + +// ----------------------------------------------------------------------------- const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName( const string& name) const { @@ -1100,23 +1453,35 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber( template inline const Type& GeneratedMessageReflection::GetRaw( const Message& message, const FieldDescriptor* field) const { + if (field->containing_oneof() && !HasOneofField(message, field)) { + return DefaultRaw(field); + } + int index = field->containing_oneof() ? + descriptor_->field_count() + field->containing_oneof()->index() : + field->index(); const void* ptr = reinterpret_cast(&message) + - offsets_[field->index()]; + offsets_[index]; return *reinterpret_cast(ptr); } template inline Type* GeneratedMessageReflection::MutableRaw( Message* message, const FieldDescriptor* field) const { - void* ptr = reinterpret_cast(message) + offsets_[field->index()]; + int index = field->containing_oneof() ? + descriptor_->field_count() + field->containing_oneof()->index() : + field->index(); + void* ptr = reinterpret_cast(message) + offsets_[index]; return reinterpret_cast(ptr); } template inline const Type& GeneratedMessageReflection::DefaultRaw( const FieldDescriptor* field) const { - const void* ptr = reinterpret_cast(default_instance_) + - offsets_[field->index()]; + const void* ptr = field->containing_oneof() ? + reinterpret_cast(default_oneof_instance_) + + offsets_[field->index()] : + reinterpret_cast(default_instance_) + + offsets_[field->index()]; return *reinterpret_cast(ptr); } @@ -1131,6 +1496,21 @@ inline uint32* GeneratedMessageReflection::MutableHasBits( return reinterpret_cast(ptr); } +inline uint32 GeneratedMessageReflection::GetOneofCase( + const Message& message, + const OneofDescriptor* oneof_descriptor) const { + const void* ptr = reinterpret_cast(&message) + + oneof_case_offset_; + return reinterpret_cast(ptr)[oneof_descriptor->index()]; +} + +inline uint32* GeneratedMessageReflection::MutableOneofCase( + Message* message, + const OneofDescriptor* oneof_descriptor) const { + void* ptr = reinterpret_cast(message) + oneof_case_offset_; + return &(reinterpret_cast(ptr)[oneof_descriptor->index()]); +} + inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet( const Message& message) const { GOOGLE_DCHECK_NE(extensions_offset_, -1); @@ -1162,6 +1542,73 @@ inline void GeneratedMessageReflection::ClearBit( MutableHasBits(message)[field->index() / 32] &= ~(1 << (field->index() % 32)); } +inline void GeneratedMessageReflection::SwapBit( + Message* message1, Message* message2, const FieldDescriptor* field) const { + bool temp_has_bit = HasBit(*message1, field); + if (HasBit(*message2, field)) { + SetBit(message1, field); + } else { + ClearBit(message1, field); + } + if (temp_has_bit) { + SetBit(message2, field); + } else { + ClearBit(message2, field); + } +} + +inline bool GeneratedMessageReflection::HasOneof( + const Message& message, const OneofDescriptor* oneof_descriptor) const { + return (GetOneofCase(message, oneof_descriptor) > 0); +} + +inline bool GeneratedMessageReflection::HasOneofField( + const Message& message, const FieldDescriptor* field) const { + return (GetOneofCase(message, field->containing_oneof()) == field->number()); +} + +inline void GeneratedMessageReflection::SetOneofCase( + Message* message, const FieldDescriptor* field) const { + *MutableOneofCase(message, field->containing_oneof()) = field->number(); +} + +inline void GeneratedMessageReflection::ClearOneofField( + Message* message, const FieldDescriptor* field) const { + if (HasOneofField(*message, field)) { + ClearOneof(message, field->containing_oneof()); + } +} + +inline void GeneratedMessageReflection::ClearOneof( + Message* message, const OneofDescriptor* oneof_descriptor) const { + // TODO(jieluo): Consider to cache the unused object instead of deleting + // it. It will be much faster if an aplication switches a lot from + // a few oneof fields. Time/space tradeoff + uint32 oneof_case = GetOneofCase(*message, oneof_descriptor); + if (oneof_case > 0) { + const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case); + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_STRING: { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + delete *MutableRaw(message, field); + break; + } + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: + delete *MutableRaw(message, field); + break; + default: + break; + } + + *MutableOneofCase(message, oneof_descriptor) = 0; + } +} + // Template implementations of basic accessors. Inline because each // template instance is only called from one location. These are // used for all types except messages. @@ -1174,14 +1621,19 @@ inline const Type& GeneratedMessageReflection::GetField( template inline void GeneratedMessageReflection::SetField( Message* message, const FieldDescriptor* field, const Type& value) const { + if (field->containing_oneof() && !HasOneofField(*message, field)) { + ClearOneof(message, field->containing_oneof()); + } *MutableRaw(message, field) = value; - SetBit(message, field); + field->containing_oneof() ? + SetOneofCase(message, field) : SetBit(message, field); } template inline Type* GeneratedMessageReflection::MutableField( Message* message, const FieldDescriptor* field) const { - SetBit(message, field); + field->containing_oneof() ? + SetOneofCase(message, field) : SetBit(message, field); return MutableRaw(message, field); } diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h index b545fa1..fc58374 100644 --- a/src/google/protobuf/generated_message_reflection.h +++ b/src/google/protobuf/generated_message_reflection.h @@ -40,21 +40,28 @@ #include #include +#include +// TODO(jasonh): Remove this once the compiler change to directly include this +// is released to components. +#include #include #include namespace google { +namespace upb { +namespace google_opensource { +class GMR_Handlers; +} // namespace google_opensource +} // namespace upb + namespace protobuf { class DescriptorPool; - // Generated code needs these to have been forward-declared. Easier to do it - // here than to print them inside every .pb.h file. - class FileDescriptor; - class EnumDescriptor; } namespace protobuf { namespace internal { +class DefaultEmptyOneof; // Defined in this file. class GeneratedMessageReflection; @@ -128,6 +135,42 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const DescriptorPool* pool, MessageFactory* factory, int object_size); + + // Similar with the construction above. Call this construction if the + // message has oneof definition. + // Parameters: + // offsets: An array of ints giving the byte offsets. + // For each oneof field, the offset is relative to the + // default_oneof_instance. These can be computed at compile + // time using the + // PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET() macro. + // For each none oneof field, the offset is related to + // the start of the message object. These can be computed + // at compile time using the + // GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET() macro. + // Besides offsets for all fields, this array also contains + // offsets for oneof unions. The offset of the i-th oneof + // union is offsets[descriptor->field_count() + i]. + // default_oneof_instance: The default instance of the oneofs. It is a + // struct holding the default value of all oneof fields + // for this message. It is only used to obtain pointers + // to default instances of oneof fields, which Get + // methods will return if the field is not set. + // oneof_case_offset: Offset in the message of an array of uint32s of + // size descriptor->oneof_decl_count(). Each uint32 + // indicates what field is set for each oneof. + // other parameters are the same with the construction above. + GeneratedMessageReflection(const Descriptor* descriptor, + const Message* default_instance, + const int offsets[], + int has_bits_offset, + int unknown_fields_offset, + int extensions_offset, + const void* default_oneof_instance, + int oneof_case_offset, + const DescriptorPool* pool, + MessageFactory* factory, + int object_size); ~GeneratedMessageReflection(); // implements Reflection ------------------------------------------- @@ -140,10 +183,16 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { bool HasField(const Message& message, const FieldDescriptor* field) const; int FieldSize(const Message& message, const FieldDescriptor* field) const; void ClearField(Message* message, const FieldDescriptor* field) const; + bool HasOneof(const Message& message, + const OneofDescriptor* oneof_descriptor) const; + void ClearOneof(Message* message, const OneofDescriptor* field) const; void RemoveLast(Message* message, const FieldDescriptor* field) const; + Message* ReleaseLast(Message* message, const FieldDescriptor* field) const; void Swap(Message* message1, Message* message2) const; + void SwapFields(Message* message1, Message* message2, + const vector& fields) const; void SwapElements(Message* message, const FieldDescriptor* field, - int index1, int index2) const; + int index1, int index2) const; void ListFields(const Message& message, vector* output) const; @@ -172,6 +221,11 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const FieldDescriptor* field, MessageFactory* factory = NULL) const; + const FieldDescriptor* GetOneofFieldDescriptor( + const Message& message, + const OneofDescriptor* oneof_descriptor) const; + + public: void SetInt32 (Message* message, const FieldDescriptor* field, int32 value) const; void SetInt64 (Message* message, @@ -193,6 +247,11 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const EnumValueDescriptor* value) const; Message* MutableMessage(Message* message, const FieldDescriptor* field, MessageFactory* factory = NULL) const; + void SetAllocatedMessage(Message* message, + Message* sub_message, + const FieldDescriptor* field) const; + Message* ReleaseMessage(Message* message, const FieldDescriptor* field, + MessageFactory* factory = NULL) const; int32 GetRepeatedInt32 (const Message& message, const FieldDescriptor* field, int index) const; @@ -270,14 +329,25 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const FieldDescriptor* FindKnownExtensionByName(const string& name) const; const FieldDescriptor* FindKnownExtensionByNumber(int number) const; + protected: + virtual void* MutableRawRepeatedField( + Message* message, const FieldDescriptor* field, FieldDescriptor::CppType, + int ctype, const Descriptor* desc) const; + private: friend class GeneratedMessage; + // To parse directly into a proto2 generated class, the class GMR_Handlers + // needs access to member offsets and hasbits. + friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers; + const Descriptor* descriptor_; const Message* default_instance_; + const void* default_oneof_instance_; const int* offsets_; int has_bits_offset_; + int oneof_case_offset_; int unknown_fields_offset_; int extensions_offset_; int object_size_; @@ -293,10 +363,17 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const FieldDescriptor* field) const; template inline const Type& DefaultRaw(const FieldDescriptor* field) const; - inline const Message* GetMessagePrototype(const FieldDescriptor* field) const; + template + inline const Type& DefaultOneofRaw(const FieldDescriptor* field) const; inline const uint32* GetHasBits(const Message& message) const; inline uint32* MutableHasBits(Message* message) const; + inline uint32 GetOneofCase( + const Message& message, + const OneofDescriptor* oneof_descriptor) const; + inline uint32* MutableOneofCase( + Message* message, + const OneofDescriptor* oneof_descriptor) const; inline const ExtensionSet& GetExtensionSet(const Message& message) const; inline ExtensionSet* MutableExtensionSet(Message* message) const; @@ -306,6 +383,26 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const FieldDescriptor* field) const; inline void ClearBit(Message* message, const FieldDescriptor* field) const; + inline void SwapBit(Message* message1, + Message* message2, + const FieldDescriptor* field) const; + + // This function only swaps the field. Should swap corresponding has_bit + // before or after using this function. + void SwapField(Message* message1, + Message* message2, + const FieldDescriptor* field) const; + + void SwapOneofField(Message* message1, + Message* message2, + const OneofDescriptor* oneof_descriptor) const; + + inline bool HasOneofField(const Message& message, + const FieldDescriptor* field) const; + inline void SetOneofCase(Message* message, + const FieldDescriptor* field) const; + inline void ClearOneofField(Message* message, + const FieldDescriptor* field) const; template inline const Type& GetField(const Message& message, @@ -359,9 +456,14 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { // be confused by an unaligned pointer. #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD) \ static_cast( \ - reinterpret_cast( \ - &reinterpret_cast(16)->FIELD) - \ - reinterpret_cast(16)) + reinterpret_cast( \ + &reinterpret_cast(16)->FIELD) - \ + reinterpret_cast(16)) + +#define PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(ONEOF, FIELD) \ + static_cast( \ + reinterpret_cast(&(ONEOF->FIELD)) \ + - reinterpret_cast(ONEOF)) // There are some places in proto2 where dynamic_cast would be useful as an // optimization. For example, take Message::MergeFrom(const Message& other). @@ -395,28 +497,6 @@ inline To dynamic_cast_if_available(From from) { #endif } -// Helper for EnumType_Parse functions: try to parse the string 'name' as an -// enum name of the given type, returning true and filling in value on success, -// or returning false and leaving value unchanged on failure. -LIBPROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor, - const string& name, - int* value); - -template -bool ParseNamedEnum(const EnumDescriptor* descriptor, - const string& name, - EnumType* value) { - int tmp; - if (!ParseNamedEnum(descriptor, name, &tmp)) return false; - *value = static_cast(tmp); - return true; -} - -// Just a wrapper around printing the name of a value. The main point of this -// function is not to be inlined, so that you can do this without including -// descriptor.h. -LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value); - } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc index a03bcdb..99c2818 100644 --- a/src/google/protobuf/generated_message_reflection_unittest.cc +++ b/src/google/protobuf/generated_message_reflection_unittest.cc @@ -207,6 +207,111 @@ TEST(GeneratedMessageReflectionTest, SwapUnknown) { EXPECT_EQ(1, message2.unknown_fields().field_count()); } +TEST(GeneratedMessageReflectionTest, SwapFields) { + unittest::TestAllTypes message1, message2; + message1.set_optional_double(12.3); + message1.mutable_repeated_int32()->Add(10); + message1.mutable_repeated_int32()->Add(20); + + message2.set_optional_string("hello"); + message2.mutable_repeated_int64()->Add(30); + + vector fields; + const Descriptor* descriptor = message1.GetDescriptor(); + fields.push_back(descriptor->FindFieldByName("optional_double")); + fields.push_back(descriptor->FindFieldByName("repeated_int32")); + fields.push_back(descriptor->FindFieldByName("optional_string")); + fields.push_back(descriptor->FindFieldByName("optional_uint64")); + + const Reflection* reflection = message1.GetReflection(); + reflection->SwapFields(&message1, &message2, fields); + + EXPECT_FALSE(message1.has_optional_double()); + EXPECT_EQ(0, message1.repeated_int32_size()); + EXPECT_TRUE(message1.has_optional_string()); + EXPECT_EQ("hello", message1.optional_string()); + EXPECT_EQ(0, message1.repeated_int64_size()); + EXPECT_FALSE(message1.has_optional_uint64()); + + EXPECT_TRUE(message2.has_optional_double()); + EXPECT_EQ(12.3, message2.optional_double()); + EXPECT_EQ(2, message2.repeated_int32_size()); + EXPECT_EQ(10, message2.repeated_int32(0)); + EXPECT_EQ(20, message2.repeated_int32(1)); + EXPECT_FALSE(message2.has_optional_string()); + EXPECT_EQ(1, message2.repeated_int64_size()); + EXPECT_FALSE(message2.has_optional_uint64()); +} + +TEST(GeneratedMessageReflectionTest, SwapFieldsAll) { + unittest::TestAllTypes message1; + unittest::TestAllTypes message2; + + TestUtil::SetAllFields(&message2); + + vector fields; + const Reflection* reflection = message1.GetReflection(); + reflection->ListFields(message2, &fields); + reflection->SwapFields(&message1, &message2, fields); + + TestUtil::ExpectAllFieldsSet(message1); + TestUtil::ExpectClear(message2); +} + +TEST(GeneratedMessageReflectionTest, SwapFieldsAllExtension) { + unittest::TestAllExtensions message1; + unittest::TestAllExtensions message2; + + TestUtil::SetAllExtensions(&message1); + + vector fields; + const Reflection* reflection = message1.GetReflection(); + reflection->ListFields(message1, &fields); + reflection->SwapFields(&message1, &message2, fields); + + TestUtil::ExpectExtensionsClear(message1); + TestUtil::ExpectAllExtensionsSet(message2); +} + +TEST(GeneratedMessageReflectionTest, SwapOneof) { + unittest::TestOneof2 message1, message2; + TestUtil::SetOneof1(&message1); + + const Reflection* reflection = message1.GetReflection(); + reflection->Swap(&message1, &message2); + + TestUtil::ExpectOneofClear(message1); + TestUtil::ExpectOneofSet1(message2); +} + +TEST(GeneratedMessageReflectionTest, SwapOneofBothSet) { + unittest::TestOneof2 message1, message2; + TestUtil::SetOneof1(&message1); + TestUtil::SetOneof2(&message2); + + const Reflection* reflection = message1.GetReflection(); + reflection->Swap(&message1, &message2); + + TestUtil::ExpectOneofSet2(message1); + TestUtil::ExpectOneofSet1(message2); +} + +TEST(GeneratedMessageReflectionTest, SwapFieldsOneof) { + unittest::TestOneof2 message1, message2; + TestUtil::SetOneof1(&message1); + + vector fields; + const Descriptor* descriptor = message1.GetDescriptor(); + for (int i = 0; i < descriptor->field_count(); i++) { + fields.push_back(descriptor->field(i)); + } + const Reflection* reflection = message1.GetReflection(); + reflection->SwapFields(&message1, &message2, fields); + + TestUtil::ExpectOneofClear(message1); + TestUtil::ExpectOneofSet1(message2); +} + TEST(GeneratedMessageReflectionTest, RemoveLast) { unittest::TestAllTypes message; TestUtil::ReflectionTester reflection_tester( @@ -225,11 +330,59 @@ TEST(GeneratedMessageReflectionTest, RemoveLastExtensions) { unittest::TestAllExtensions::descriptor()); TestUtil::SetAllExtensions(&message); + reflection_tester.RemoveLastRepeatedsViaReflection(&message); TestUtil::ExpectLastRepeatedExtensionsRemoved(message); } +TEST(GeneratedMessageReflectionTest, ReleaseLast) { + unittest::TestAllTypes message; + const Descriptor* descriptor = message.GetDescriptor(); + TestUtil::ReflectionTester reflection_tester(descriptor); + + TestUtil::SetAllFields(&message); + + reflection_tester.ReleaseLastRepeatedsViaReflection(&message, false); + + TestUtil::ExpectLastRepeatedsReleased(message); + + // Now test that we actually release the right message. + message.Clear(); + TestUtil::SetAllFields(&message); + ASSERT_EQ(2, message.repeated_foreign_message_size()); + const protobuf_unittest::ForeignMessage* expected = + message.mutable_repeated_foreign_message(1); + scoped_ptr released(message.GetReflection()->ReleaseLast( + &message, descriptor->FindFieldByName("repeated_foreign_message"))); + EXPECT_EQ(expected, released.get()); +} + +TEST(GeneratedMessageReflectionTest, ReleaseLastExtensions) { + unittest::TestAllExtensions message; + const Descriptor* descriptor = message.GetDescriptor(); + TestUtil::ReflectionTester reflection_tester(descriptor); + + TestUtil::SetAllExtensions(&message); + + reflection_tester.ReleaseLastRepeatedsViaReflection(&message, true); + + TestUtil::ExpectLastRepeatedExtensionsReleased(message); + + // Now test that we actually release the right message. + message.Clear(); + TestUtil::SetAllExtensions(&message); + ASSERT_EQ(2, message.ExtensionSize( + unittest::repeated_foreign_message_extension)); + const protobuf_unittest::ForeignMessage* expected = message.MutableExtension( + unittest::repeated_foreign_message_extension, 1); + scoped_ptr released(message.GetReflection()->ReleaseLast( + &message, descriptor->file()->FindExtensionByName( + "repeated_foreign_message_extension"))); + EXPECT_EQ(expected, released.get()); + +} + TEST(GeneratedMessageReflectionTest, SwapRepeatedElements) { unittest::TestAllTypes message; TestUtil::ReflectionTester reflection_tester( @@ -327,7 +480,265 @@ TEST(GeneratedMessageReflectionTest, FindKnownExtensionByName) { FindKnownExtensionByName(extension1->full_name()) == NULL); } -#ifdef GTEST_HAS_DEATH_TEST +TEST(GeneratedMessageReflectionTest, SetAllocatedMessageTest) { + unittest::TestAllTypes from_message1; + unittest::TestAllTypes from_message2; + unittest::TestAllTypes to_message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllTypes::descriptor()); + reflection_tester.SetAllFieldsViaReflection(&from_message1); + reflection_tester.SetAllFieldsViaReflection(&from_message2); + + // Before moving fields, we expect the nested messages to be NULL. + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::IS_NULL); + + // After fields are moved we should get non-NULL releases. + reflection_tester.SetAllocatedOptionalMessageFieldsToMessageViaReflection( + &from_message1, &to_message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::NOT_NULL); + + // Another move to make sure that we can SetAllocated several times. + reflection_tester.SetAllocatedOptionalMessageFieldsToMessageViaReflection( + &from_message2, &to_message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::NOT_NULL); + + // After SetAllocatedOptionalMessageFieldsToNullViaReflection() we expect the + // releases to be NULL again. + reflection_tester.SetAllocatedOptionalMessageFieldsToNullViaReflection( + &to_message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::IS_NULL); +} + +TEST(GeneratedMessageReflectionTest, SetAllocatedExtensionMessageTest) { + unittest::TestAllExtensions from_message1; + unittest::TestAllExtensions from_message2; + unittest::TestAllExtensions to_message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllExtensions::descriptor()); + reflection_tester.SetAllFieldsViaReflection(&from_message1); + reflection_tester.SetAllFieldsViaReflection(&from_message2); + + // Before moving fields, we expect the nested messages to be NULL. + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::IS_NULL); + + // After fields are moved we should get non-NULL releases. + reflection_tester.SetAllocatedOptionalMessageFieldsToMessageViaReflection( + &from_message1, &to_message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::NOT_NULL); + + // Another move to make sure that we can SetAllocated several times. + reflection_tester.SetAllocatedOptionalMessageFieldsToMessageViaReflection( + &from_message2, &to_message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::NOT_NULL); + + // After SetAllocatedOptionalMessageFieldsToNullViaReflection() we expect the + // releases to be NULL again. + reflection_tester.SetAllocatedOptionalMessageFieldsToNullViaReflection( + &to_message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::IS_NULL); +} + +TEST(GeneratedMessageReflectionTest, ListFieldsOneOf) { + unittest::TestOneof2 message; + TestUtil::SetOneof1(&message); + + const Reflection* reflection = message.GetReflection(); + vector fields; + reflection->ListFields(message, &fields); + EXPECT_EQ(4, fields.size()); +} + +TEST(GeneratedMessageReflectionTest, Oneof) { + unittest::TestOneof2 message; + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* reflection = message.GetReflection(); + + // Check default values. + EXPECT_EQ(0, reflection->GetInt32( + message, descriptor->FindFieldByName("foo_int"))); + EXPECT_EQ("", reflection->GetString( + message, descriptor->FindFieldByName("foo_string"))); + EXPECT_EQ("", reflection->GetString( + message, descriptor->FindFieldByName("foo_cord"))); + EXPECT_EQ("", reflection->GetString( + message, descriptor->FindFieldByName("foo_string_piece"))); + EXPECT_EQ("", reflection->GetString( + message, descriptor->FindFieldByName("foo_bytes"))); + EXPECT_EQ(unittest::TestOneof2::FOO, reflection->GetEnum( + message, descriptor->FindFieldByName("foo_enum"))->number()); + EXPECT_EQ(&unittest::TestOneof2::NestedMessage::default_instance(), + &reflection->GetMessage( + message, descriptor->FindFieldByName("foo_message"))); + EXPECT_EQ(&unittest::TestOneof2::FooGroup::default_instance(), + &reflection->GetMessage( + message, descriptor->FindFieldByName("foogroup"))); + EXPECT_NE(&unittest::TestOneof2::FooGroup::default_instance(), + &reflection->GetMessage( + message, descriptor->FindFieldByName("foo_lazy_message"))); + EXPECT_EQ(5, reflection->GetInt32( + message, descriptor->FindFieldByName("bar_int"))); + EXPECT_EQ("STRING", reflection->GetString( + message, descriptor->FindFieldByName("bar_string"))); + EXPECT_EQ("CORD", reflection->GetString( + message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_EQ("SPIECE", reflection->GetString( + message, descriptor->FindFieldByName("bar_string_piece"))); + EXPECT_EQ("BYTES", reflection->GetString( + message, descriptor->FindFieldByName("bar_bytes"))); + EXPECT_EQ(unittest::TestOneof2::BAR, reflection->GetEnum( + message, descriptor->FindFieldByName("bar_enum"))->number()); + + // Check Set functions. + reflection->SetInt32( + &message, descriptor->FindFieldByName("foo_int"), 123); + EXPECT_EQ(123, reflection->GetInt32( + message, descriptor->FindFieldByName("foo_int"))); + reflection->SetString( + &message, descriptor->FindFieldByName("foo_string"), "abc"); + EXPECT_EQ("abc", reflection->GetString( + message, descriptor->FindFieldByName("foo_string"))); + reflection->SetString( + &message, descriptor->FindFieldByName("foo_bytes"), "bytes"); + EXPECT_EQ("bytes", reflection->GetString( + message, descriptor->FindFieldByName("foo_bytes"))); + reflection->SetString( + &message, descriptor->FindFieldByName("bar_cord"), "change_cord"); + EXPECT_EQ("change_cord", reflection->GetString( + message, descriptor->FindFieldByName("bar_cord"))); + reflection->SetString( + &message, descriptor->FindFieldByName("bar_string_piece"), + "change_spiece"); + EXPECT_EQ("change_spiece", reflection->GetString( + message, descriptor->FindFieldByName("bar_string_piece"))); +} + +TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageTest) { + unittest::TestOneof2 from_message1; + unittest::TestOneof2 from_message2; + unittest::TestOneof2 to_message; + const Descriptor* descriptor = unittest::TestOneof2::descriptor(); + const Reflection* reflection = to_message.GetReflection(); + + Message* released = reflection->ReleaseMessage( + &to_message, descriptor->FindFieldByName("foo_lazy_message")); + EXPECT_TRUE(released == NULL); + released = reflection->ReleaseMessage( + &to_message, descriptor->FindFieldByName("foo_message")); + EXPECT_TRUE(released == NULL); + + TestUtil::ReflectionTester::SetOneofViaReflection(&from_message1); + TestUtil::ReflectionTester::ExpectOneofSetViaReflection(from_message1); + + TestUtil::ReflectionTester:: + SetAllocatedOptionalMessageFieldsToMessageViaReflection( + &from_message1, &to_message); + const Message& sub_message = reflection->GetMessage( + to_message, descriptor->FindFieldByName("foo_lazy_message")); + released = reflection->ReleaseMessage( + &to_message, descriptor->FindFieldByName("foo_lazy_message")); + EXPECT_TRUE(released != NULL); + EXPECT_EQ(&sub_message, released); + delete released; + + TestUtil::ReflectionTester::SetOneofViaReflection(&from_message2); + + reflection->MutableMessage( + &from_message2, descriptor->FindFieldByName("foo_message")); + + TestUtil::ReflectionTester:: + SetAllocatedOptionalMessageFieldsToMessageViaReflection( + &from_message2, &to_message); + + const Message& sub_message2 = reflection->GetMessage( + to_message, descriptor->FindFieldByName("foo_message")); + released = reflection->ReleaseMessage( + &to_message, descriptor->FindFieldByName("foo_message")); + EXPECT_TRUE(released != NULL); + EXPECT_EQ(&sub_message2, released); + delete released; +} + +TEST(GeneratedMessageReflectionTest, ReleaseMessageTest) { + unittest::TestAllTypes message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllTypes::descriptor()); + + // When nothing is set, we expect all released messages to be NULL. + reflection_tester.ExpectMessagesReleasedViaReflection( + &message, TestUtil::ReflectionTester::IS_NULL); + + // After fields are set we should get non-NULL releases. + reflection_tester.SetAllFieldsViaReflection(&message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &message, TestUtil::ReflectionTester::NOT_NULL); + + // After Clear() we may or may not get a message from ReleaseMessage(). + // This is implementation specific. + reflection_tester.SetAllFieldsViaReflection(&message); + message.Clear(); + reflection_tester.ExpectMessagesReleasedViaReflection( + &message, TestUtil::ReflectionTester::CAN_BE_NULL); + + // Test a different code path for setting after releasing. + TestUtil::SetAllFields(&message); + TestUtil::ExpectAllFieldsSet(message); +} + +TEST(GeneratedMessageReflectionTest, ReleaseExtensionMessageTest) { + unittest::TestAllExtensions message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllExtensions::descriptor()); + + // When nothing is set, we expect all released messages to be NULL. + reflection_tester.ExpectMessagesReleasedViaReflection( + &message, TestUtil::ReflectionTester::IS_NULL); + + // After fields are set we should get non-NULL releases. + reflection_tester.SetAllFieldsViaReflection(&message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &message, TestUtil::ReflectionTester::NOT_NULL); + + // After Clear() we may or may not get a message from ReleaseMessage(). + // This is implementation specific. + reflection_tester.SetAllFieldsViaReflection(&message); + message.Clear(); + reflection_tester.ExpectMessagesReleasedViaReflection( + &message, TestUtil::ReflectionTester::CAN_BE_NULL); + + // Test a different code path for setting after releasing. + TestUtil::SetAllExtensions(&message); + TestUtil::ExpectAllExtensionsSet(message); +} + +TEST(GeneratedMessageReflectionTest, ReleaseOneofMessageTest) { + unittest::TestOneof2 message; + TestUtil::ReflectionTester::SetOneofViaReflection(&message); + + const Descriptor* descriptor = unittest::TestOneof2::descriptor(); + const Reflection* reflection = message.GetReflection(); + const Message& sub_message = reflection->GetMessage( + message, descriptor->FindFieldByName("foo_lazy_message")); + Message* released = reflection->ReleaseMessage( + &message, descriptor->FindFieldByName("foo_lazy_message")); + + EXPECT_TRUE(released != NULL); + EXPECT_EQ(&sub_message, released); + delete released; + + released = reflection->ReleaseMessage( + &message, descriptor->FindFieldByName("foo_lazy_message")); + EXPECT_TRUE(released == NULL); +} + +#ifdef PROTOBUF_HAS_DEATH_TEST TEST(GeneratedMessageReflectionTest, UsageErrors) { unittest::TestAllTypes message; @@ -376,7 +787,7 @@ TEST(GeneratedMessageReflectionTest, UsageErrors) { #undef f } -#endif // GTEST_HAS_DEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST } // namespace diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc index 7ac015d..c0726a6 100644 --- a/src/google/protobuf/generated_message_util.cc +++ b/src/google/protobuf/generated_message_util.cc @@ -36,6 +36,7 @@ #include + namespace google { namespace protobuf { namespace internal { @@ -47,6 +48,13 @@ double NaN() { return std::numeric_limits::quiet_NaN(); } +const ::std::string* empty_string_; +GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_); + +void InitEmptyString() { + empty_string_ = new string; +} + } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h index daa16f7..b6c0cf9 100644 --- a/src/google/protobuf/generated_message_util.h +++ b/src/google/protobuf/generated_message_util.h @@ -38,19 +38,18 @@ #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ -#include +#include +#include +#include +#include namespace google { -namespace protobuf { - namespace io { - class CodedInputStream; // coded_stream.h - } -} namespace protobuf { namespace internal { + // Annotation for the compiler to emit a deprecation message if a field marked // with option 'deprecated=true' is used in the code, or for other things in // generated code which are deprecated. @@ -58,17 +57,54 @@ namespace internal { // For internal use in the pb.cc files, deprecation warnings are suppressed // there. #undef DEPRECATED_PROTOBUF_FIELD -#if !defined(INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION) -# define PROTOBUF_DEPRECATED GOOGLE_ATTRIBUTE_DEPRECATED -#else -# define PROTOBUF_DEPRECATED -#endif +#define PROTOBUF_DEPRECATED // Constants for special floating point values. LIBPROTOBUF_EXPORT double Infinity(); LIBPROTOBUF_EXPORT double NaN(); +// TODO(jieluo): Change to template. We have tried to use template, +// but it causes net/rpc/python:rpcutil_test fail (the empty string will +// init twice). It may related to swig. Change to template after we +// found the solution. + +// Default empty string object. Don't use the pointer directly. Instead, call +// GetEmptyString() to get the reference. +LIBPROTOBUF_EXPORT extern const ::std::string* empty_string_; +LIBPROTOBUF_EXPORT extern ProtobufOnceType empty_string_once_init_; +LIBPROTOBUF_EXPORT void InitEmptyString(); + + +LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyStringAlreadyInited() { + assert(empty_string_ != NULL); + return *empty_string_; +} +LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() { + ::google::protobuf::GoogleOnceInit(&empty_string_once_init_, &InitEmptyString); + return GetEmptyStringAlreadyInited(); +} + +// Defined in generated_message_reflection.cc -- not actually part of the lite +// library. +// +// TODO(jasonh): The various callers get this declaration from a variety of +// places: probably in most cases repeated_field.h. Clean these up so they all +// get the declaration from this file. +LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str); + + +// True if IsInitialized() is true for all elements of t. Type is expected +// to be a RepeatedPtrField. It's useful to have this +// helper here to keep the protobuf compiler from ever having to emit loops in +// IsInitialized() methods. We want the C++ compiler to inline this or not +// as it sees fit. +template bool AllAreInitialized(const Type& t) { + for (int i = t.size(); --i >= 0; ) { + if (!t.Get(i).IsInitialized()) return false; + } + return true; +} } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index 6a91a13..f6a8453 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -43,7 +43,7 @@ #include #include #include -#include +#include namespace google { @@ -56,10 +56,36 @@ static const int kMaxVarintBytes = 10; static const int kMaxVarint32Bytes = 5; +inline bool NextNonEmpty(ZeroCopyInputStream* input, + const void** data, int* size) { + bool success; + do { + success = input->Next(data, size); + } while (success && *size == 0); + return success; +} + } // namespace // CodedInputStream ================================================== +CodedInputStream::~CodedInputStream() { + if (input_ != NULL) { + BackUpInputToCurrentPosition(); + } + + if (total_bytes_warning_threshold_ == -2) { + GOOGLE_LOG(WARNING) << "The total number of bytes read was " << total_bytes_read_; + } +} + +// Static. +int CodedInputStream::default_recursion_limit_ = 100; + + +void CodedOutputStream::EnableAliasing(bool enabled) { + aliasing_enabled_ = enabled && output_->AllowsAliasing(); +} void CodedInputStream::BackUpInputToCurrentPosition() { int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_; @@ -89,8 +115,7 @@ inline void CodedInputStream::RecomputeBufferLimits() { CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) { // Current position relative to the beginning of the stream. - int current_position = total_bytes_read_ - - (BufferSize() + buffer_size_after_limit_); + int current_position = CurrentPosition(); Limit old_limit = current_limit_; @@ -124,10 +149,9 @@ void CodedInputStream::PopLimit(Limit limit) { legitimate_message_end_ = false; } -int CodedInputStream::BytesUntilLimit() { +int CodedInputStream::BytesUntilLimit() const { if (current_limit_ == INT_MAX) return -1; - int current_position = total_bytes_read_ - - (BufferSize() + buffer_size_after_limit_); + int current_position = CurrentPosition(); return current_limit_ - current_position; } @@ -136,13 +160,22 @@ void CodedInputStream::SetTotalBytesLimit( int total_bytes_limit, int warning_threshold) { // Make sure the limit isn't already past, since this could confuse other // code. - int current_position = total_bytes_read_ - - (BufferSize() + buffer_size_after_limit_); + int current_position = CurrentPosition(); total_bytes_limit_ = max(current_position, total_bytes_limit); - total_bytes_warning_threshold_ = warning_threshold; + if (warning_threshold >= 0) { + total_bytes_warning_threshold_ = warning_threshold; + } else { + // warning_threshold is negative + total_bytes_warning_threshold_ = -1; + } RecomputeBufferLimits(); } +int CodedInputStream::BytesUntilTotalBytesLimit() const { + if (total_bytes_limit_ == INT_MAX) return -1; + return total_bytes_limit_ - CurrentPosition(); +} + void CodedInputStream::PrintTotalBytesLimitError() { GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too " "big (more than " << total_bytes_limit_ @@ -223,6 +256,14 @@ bool CodedInputStream::ReadStringFallback(string* buffer, int size) { buffer->clear(); } + int closest_limit = min(current_limit_, total_bytes_limit_); + if (closest_limit != INT_MAX) { + int bytes_to_limit = closest_limit - CurrentPosition(); + if (bytes_to_limit > 0 && size > 0 && size <= bytes_to_limit) { + buffer->reserve(size); + } + } + int current_buffer_size; while ((current_buffer_size = BufferSize()) < size) { // Some STL implementations "helpfully" crash on buffer->append(NULL, 0). @@ -289,11 +330,16 @@ inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) { uint32 b; uint32 result; - b = *(ptr++); result = (b & 0x7F) ; if (!(b & 0x80)) goto done; - b = *(ptr++); result |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; - b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done; - b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done; - b = *(ptr++); result |= b << 28; if (!(b & 0x80)) goto done; + b = *(ptr++); result = b ; if (!(b & 0x80)) goto done; + result -= 0x80; + b = *(ptr++); result += b << 7; if (!(b & 0x80)) goto done; + result -= 0x80 << 7; + b = *(ptr++); result += b << 14; if (!(b & 0x80)) goto done; + result -= 0x80 << 14; + b = *(ptr++); result += b << 21; if (!(b & 0x80)) goto done; + result -= 0x80 << 21; + b = *(ptr++); result += b << 28; if (!(b & 0x80)) goto done; + // "result -= 0x80 << 28" is irrevelant. // If the input is larger than 32 bits, we still need to read it all // and discard the high-order bits. @@ -323,8 +369,8 @@ bool CodedInputStream::ReadVarint32Slow(uint32* value) { bool CodedInputStream::ReadVarint32Fallback(uint32* value) { if (BufferSize() >= kMaxVarintBytes || - // Optimization: If the varint ends at exactly the end of the buffer, - // we can detect that and still use the fast path. + // Optimization: We're also safe if the buffer is non-empty and it ends + // with a byte that would terminate a varint. (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) { const uint8* end = ReadVarint32FromArray(buffer_, value); if (end == NULL) return false; @@ -359,16 +405,17 @@ uint32 CodedInputStream::ReadTagSlow() { // For the slow path, just do a 64-bit read. Try to optimize for one-byte tags // again, since we have now refreshed the buffer. - uint64 result; + uint64 result = 0; if (!ReadVarint64(&result)) return 0; return static_cast(result); } uint32 CodedInputStream::ReadTagFallback() { - if (BufferSize() >= kMaxVarintBytes || - // Optimization: If the varint ends at exactly the end of the buffer, - // we can detect that and still use the fast path. - (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) { + const int buf_size = BufferSize(); + if (buf_size >= kMaxVarintBytes || + // Optimization: We're also safe if the buffer is non-empty and it ends + // with a byte that would terminate a varint. + (buf_size > 0 && !(buffer_end_[-1] & 0x80))) { uint32 tag; const uint8* end = ReadVarint32FromArray(buffer_, &tag); if (end == NULL) { @@ -379,7 +426,9 @@ uint32 CodedInputStream::ReadTagFallback() { } else { // We are commonly at a limit when attempting to read tags. Try to quickly // detect this case without making another function call. - if (buffer_ == buffer_end_ && buffer_size_after_limit_ > 0 && + if ((buf_size == 0) && + ((buffer_size_after_limit_ > 0) || + (total_bytes_read_ == current_limit_)) && // Make sure that the limit we hit is not total_bytes_limit_, since // in that case we still need to call Refresh() so that it prints an // error. @@ -417,8 +466,8 @@ bool CodedInputStream::ReadVarint64Slow(uint64* value) { bool CodedInputStream::ReadVarint64Fallback(uint64* value) { if (BufferSize() >= kMaxVarintBytes || - // Optimization: If the varint ends at exactly the end of the buffer, - // we can detect that and still use the fast path. + // Optimization: We're also safe if the buffer is non-empty and it ends + // with a byte that would terminate a varint. (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) { // Fast path: We have enough bytes left in the buffer to guarantee that // this read won't cross the end, so we can skip the checks. @@ -430,20 +479,30 @@ bool CodedInputStream::ReadVarint64Fallback(uint64* value) { // processors. uint32 part0 = 0, part1 = 0, part2 = 0; - b = *(ptr++); part0 = (b & 0x7F) ; if (!(b & 0x80)) goto done; - b = *(ptr++); part0 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; - b = *(ptr++); part0 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done; - b = *(ptr++); part0 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done; - b = *(ptr++); part1 = (b & 0x7F) ; if (!(b & 0x80)) goto done; - b = *(ptr++); part1 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; - b = *(ptr++); part1 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done; - b = *(ptr++); part1 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done; - b = *(ptr++); part2 = (b & 0x7F) ; if (!(b & 0x80)) goto done; - b = *(ptr++); part2 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; + b = *(ptr++); part0 = b ; if (!(b & 0x80)) goto done; + part0 -= 0x80; + b = *(ptr++); part0 += b << 7; if (!(b & 0x80)) goto done; + part0 -= 0x80 << 7; + b = *(ptr++); part0 += b << 14; if (!(b & 0x80)) goto done; + part0 -= 0x80 << 14; + b = *(ptr++); part0 += b << 21; if (!(b & 0x80)) goto done; + part0 -= 0x80 << 21; + b = *(ptr++); part1 = b ; if (!(b & 0x80)) goto done; + part1 -= 0x80; + b = *(ptr++); part1 += b << 7; if (!(b & 0x80)) goto done; + part1 -= 0x80 << 7; + b = *(ptr++); part1 += b << 14; if (!(b & 0x80)) goto done; + part1 -= 0x80 << 14; + b = *(ptr++); part1 += b << 21; if (!(b & 0x80)) goto done; + part1 -= 0x80 << 21; + b = *(ptr++); part2 = b ; if (!(b & 0x80)) goto done; + part2 -= 0x80; + b = *(ptr++); part2 += b << 7; if (!(b & 0x80)) goto done; + // "part2 -= 0x80 << 7" is irrelevant because (0x80 << 7) << 56 is 0. // We have overrun the maximum size of a varint (10 bytes). The data // must be corrupt. - return NULL; + return false; done: Advance(ptr - buffer_); @@ -483,13 +542,13 @@ bool CodedInputStream::Refresh() { "CodedInputStream::SetTotalBytesLimit() in " "google/protobuf/io/coded_stream.h."; - // Don't warn again for this stream. - total_bytes_warning_threshold_ = -1; + // Don't warn again for this stream, and print total size at the end. + total_bytes_warning_threshold_ = -2; } const void* void_buffer; int buffer_size; - if (input_->Next(&void_buffer, &buffer_size)) { + if (NextNonEmpty(input_, &void_buffer, &buffer_size)) { buffer_ = reinterpret_cast(void_buffer); buffer_end_ = buffer_ + buffer_size; GOOGLE_CHECK_GE(buffer_size, 0); @@ -528,7 +587,8 @@ CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output) buffer_(NULL), buffer_size_(0), total_bytes_(0), - had_error_(false) { + had_error_(false), + aliasing_enabled_(false) { // Eagerly Refresh() so buffer space is immediately available. Refresh(); // The Refresh() may have failed. If the client doesn't write any data, @@ -582,6 +642,23 @@ uint8* CodedOutputStream::WriteRawToArray( } +void CodedOutputStream::WriteAliasedRaw(const void* data, int size) { + if (size < buffer_size_ + ) { + WriteRaw(data, size); + } else { + if (buffer_size_ > 0) { + output_->BackUp(buffer_size_); + total_bytes_ -= buffer_size_; + buffer_ = NULL; + buffer_size_ = 0; + } + + total_bytes_ += size; + had_error_ |= !output_->WriteAliasedRaw(data, size); + } +} + void CodedOutputStream::WriteLittleEndian32(uint32 value) { uint8 bytes[sizeof(value)]; @@ -825,6 +902,13 @@ int CodedOutputStream::VarintSize64(uint64 value) { } } +uint8* CodedOutputStream::WriteStringWithSizeToArray(const string& str, + uint8* target) { + GOOGLE_DCHECK_LE(str.size(), kuint32max); + target = WriteVarint32ToArray(str.size(), target); + return WriteStringToArray(str, target); +} + } // namespace io } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index e5f6161..50a03a1 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -110,14 +110,27 @@ #define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ #include -#ifndef _MSC_VER -#include -#endif // !_MSC_VER +#ifdef _MSC_VER + #if defined(_M_IX86) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif + #if _MSC_VER >= 1300 + // If MSVC has "/RTCc" set, it will complain about truncating casts at + // runtime. This file contains some intentional truncating casts. + #pragma runtime_checks("c", off) + #endif +#else + #include // __BYTE_ORDER + #if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif +#endif #include -#include // for GOOGLE_PREDICT_TRUE macro -namespace google { +namespace google { namespace protobuf { class DescriptorPool; @@ -157,6 +170,9 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // successfully and the stream's byte limit. ~CodedInputStream(); + // Return true if this CodedInputStream reads from a flat array instead of + // a ZeroCopyInputStream. + inline bool IsFlat() const; // Skips a number of bytes. Returns false if an underlying read error // occurs. @@ -217,11 +233,22 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Read a tag. This calls ReadVarint32() and returns the result, or returns // zero (which is not a valid tag) if ReadVarint32() fails. Also, it updates // the last tag value, which can be checked with LastTagWas(). - // Always inline because this is only called in once place per parse loop + // Always inline because this is only called in one place per parse loop // but it is called for every iteration of said loop, so it should be fast. // GCC doesn't want to inline this by default. uint32 ReadTag() GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + // This usually a faster alternative to ReadTag() when cutoff is a manifest + // constant. It does particularly well for cutoff >= 127. The first part + // of the return value is the tag that was read, though it can also be 0 in + // the cases where ReadTag() would return 0. If the second part is true + // then the tag is known to be in [0, cutoff]. If not, the tag either is + // above cutoff or is 0. (There's intentional wiggle room when tag is 0, + // because that can arise in several ways, and for best performance we want + // to avoid an extra "is tag == 0?" check here.) + inline std::pair ReadTagWithCutoff(uint32 cutoff) + GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + // Usually returns true if calling ReadVarint32() now would produce the given // value. Will always return false if ReadVarint32() would not return the // given value. If ExpectTag() returns true, it also advances past @@ -248,8 +275,8 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // zero, and ConsumedEntireMessage() will return true. bool ExpectAtEnd(); - // If the last call to ReadTag() returned the given value, returns true. - // Otherwise, returns false; + // If the last call to ReadTag() or ReadTagWithCutoff() returned the + // given value, returns true. Otherwise, returns false; // // This is needed because parsers for some types of embedded messages // (with field type TYPE_GROUP) don't actually know that they've reached the @@ -298,7 +325,10 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Returns the number of bytes left until the nearest limit on the // stack is hit, or -1 if no limits are in place. - int BytesUntilLimit(); + int BytesUntilLimit() const; + + // Returns current position relative to the beginning of the input stream. + int CurrentPosition() const; // Total Bytes Limit ----------------------------------------------- // To prevent malicious users from sending excessively large messages @@ -314,8 +344,9 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // cause integer overflows is 512MB. The default limit is 64MB. Apps // should set shorter limits if possible. If warning_threshold is not -1, // a warning will be printed to stderr after warning_threshold bytes are - // read. An error will always be printed to stderr if the limit is - // reached. + // read. For backwards compatibility all negative values get squashed to -1, + // as other negative values might have special internal meanings. + // An error will always be printed to stderr if the limit is reached. // // This is unrelated to PushLimit()/PopLimit(). // @@ -336,15 +367,20 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // something unusual. void SetTotalBytesLimit(int total_bytes_limit, int warning_threshold); + // The Total Bytes Limit minus the Current Position, or -1 if there + // is no Total Bytes Limit. + int BytesUntilTotalBytesLimit() const; + // Recursion Limit ------------------------------------------------- // To prevent corrupt or malicious messages from causing stack overflows, // we must keep track of the depth of recursion when parsing embedded // messages and groups. CodedInputStream keeps track of this because it // is the only object that is passed down the stack during parsing. - // Sets the maximum recursion depth. The default is 64. + // Sets the maximum recursion depth. The default is 100. void SetRecursionLimit(int limit); + // Increments the current recursion depth. Returns true if the depth is // under the limit, false if it has gone over. bool IncrementRecursionDepth(); @@ -420,7 +456,8 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // // Note that this feature is ignored when parsing "lite" messages as they do // not have descriptors. - void SetExtensionRegistry(DescriptorPool* pool, MessageFactory* factory); + void SetExtensionRegistry(const DescriptorPool* pool, + MessageFactory* factory); // Get the DescriptorPool set via SetExtensionRegistry(), or NULL if no pool // has been provided. @@ -444,7 +481,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { int overflow_bytes_; // LastTagWas() stuff. - uint32 last_tag_; // result of last ReadTag(). + uint32 last_tag_; // result of last ReadTag() or ReadTagWithCutoff(). // This is set true by ReadTag{Fallback/Slow}() if it is called when exactly // at EOF, or by ExpectAtEnd() when it returns true. This happens when we @@ -469,6 +506,11 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Maximum number of bytes to read, period. This is unrelated to // current_limit_. Set using SetTotalBytesLimit(). int total_bytes_limit_; + + // If positive/0: Limit for bytes read after which a warning due to size + // should be logged. + // If -1: Printing of warning disabled. Can be set by client. + // If -2: Internal: Limit has been reached, print full size when destructing. int total_bytes_warning_threshold_; // Current recursion depth, controlled by IncrementRecursionDepth() and @@ -521,12 +563,13 @@ class LIBPROTOBUF_EXPORT CodedInputStream { bool ReadStringFallback(string* buffer, int size); // Return the size of the buffer. - uint32 BufferSize() const; + int BufferSize() const; static const int kDefaultTotalBytesLimit = 64 << 20; // 64MB static const int kDefaultTotalBytesWarningThreshold = 32 << 20; // 32MB - static const int kDefaultRecursionLimit = 64; + + static int default_recursion_limit_; // 100 by default. }; // Class which encodes and writes binary data which is composed of varint- @@ -554,7 +597,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // char text[] = "Hello world!"; // // int coded_size = sizeof(magic_number) + -// CodedOutputStream::Varint32Size(strlen(text)) + +// CodedOutputStream::VarintSize32(strlen(text)) + // strlen(text); // // uint8* buffer = @@ -610,6 +653,9 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // Write raw bytes, copying them from the given buffer. void WriteRaw(const void* buffer, int size); + // Like WriteRaw() but will try to write aliased data if aliasing is + // turned on. + void WriteRawMaybeAliased(const void* data, int size); // Like WriteRaw() but writing directly to the target array. // This is _not_ inlined, as the compiler often optimizes memcpy into inline // copy loops. Since this gets called by every field with string or bytes @@ -621,8 +667,21 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { void WriteString(const string& str); // Like WriteString() but writing directly to the target array. static uint8* WriteStringToArray(const string& str, uint8* target); + // Write the varint-encoded size of str followed by str. + static uint8* WriteStringWithSizeToArray(const string& str, uint8* target); + // Instructs the CodedOutputStream to allow the underlying + // ZeroCopyOutputStream to hold pointers to the original structure instead of + // copying, if it supports it (i.e. output->AllowsAliasing() is true). If the + // underlying stream does not support aliasing, then enabling it has no + // affect. For now, this only affects the behavior of + // WriteRawMaybeAliased(). + // + // NOTE: It is caller's responsibility to ensure that the chunk of memory + // remains live until all of the data has been consumed from the stream. + void EnableAliasing(bool enabled); + // Write a 32-bit little-endian integer. void WriteLittleEndian32(uint32 value); // Like WriteLittleEndian32() but writing directly to the target array. @@ -667,6 +726,21 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // If negative, 10 bytes. Otheriwse, same as VarintSize32(). static int VarintSize32SignExtended(int32 value); + // Compile-time equivalent of VarintSize32(). + template + struct StaticVarintSize32 { + static const int value = + (Value < (1 << 7)) + ? 1 + : (Value < (1 << 14)) + ? 2 + : (Value < (1 << 21)) + ? 3 + : (Value < (1 << 28)) + ? 4 + : 5; + }; + // Returns the total number of bytes written since this object was created. inline int ByteCount() const; @@ -682,6 +756,7 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { int buffer_size_; int total_bytes_; // Sum of sizes of all buffers seen so far. bool had_error_; // Whether an error occurred during output. + bool aliasing_enabled_; // See EnableAliasing(). // Advance the buffer by a given number of bytes. void Advance(int amount); @@ -690,6 +765,10 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // Advance(buffer_size_). bool Refresh(); + // Like WriteRaw() but may avoid copying if the underlying + // ZeroCopyOutputStream supports it. + void WriteAliasedRaw(const void* buffer, int size); + static uint8* WriteVarint32FallbackToArray(uint32 value, uint8* target); // Always-inlined versions of WriteVarint* functions so that code can be @@ -735,8 +814,7 @@ inline bool CodedInputStream::ReadVarint64(uint64* value) { inline const uint8* CodedInputStream::ReadLittleEndian32FromArray( const uint8* buffer, uint32* value) { -#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \ - defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN +#if defined(PROTOBUF_LITTLE_ENDIAN) memcpy(value, buffer, sizeof(*value)); return buffer + sizeof(*value); #else @@ -751,8 +829,7 @@ inline const uint8* CodedInputStream::ReadLittleEndian32FromArray( inline const uint8* CodedInputStream::ReadLittleEndian64FromArray( const uint8* buffer, uint64* value) { -#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \ - defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN +#if defined(PROTOBUF_LITTLE_ENDIAN) memcpy(value, buffer, sizeof(*value)); return buffer + sizeof(*value); #else @@ -771,9 +848,8 @@ inline const uint8* CodedInputStream::ReadLittleEndian64FromArray( } inline bool CodedInputStream::ReadLittleEndian32(uint32* value) { -#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \ - defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN - if (GOOGLE_PREDICT_TRUE(BufferSize() >= sizeof(*value))) { +#if defined(PROTOBUF_LITTLE_ENDIAN) + if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { memcpy(value, buffer_, sizeof(*value)); Advance(sizeof(*value)); return true; @@ -786,9 +862,8 @@ inline bool CodedInputStream::ReadLittleEndian32(uint32* value) { } inline bool CodedInputStream::ReadLittleEndian64(uint64* value) { -#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \ - defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN - if (GOOGLE_PREDICT_TRUE(BufferSize() >= sizeof(*value))) { +#if defined(PROTOBUF_LITTLE_ENDIAN) + if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { memcpy(value, buffer_, sizeof(*value)); Advance(sizeof(*value)); return true; @@ -811,6 +886,45 @@ inline uint32 CodedInputStream::ReadTag() { } } +inline std::pair CodedInputStream::ReadTagWithCutoff( + uint32 cutoff) { + // In performance-sensitive code we can expect cutoff to be a compile-time + // constant, and things like "cutoff >= kMax1ByteVarint" to be evaluated at + // compile time. + if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) { + // Hot case: buffer_ non_empty, buffer_[0] in [1, 128). + // TODO(gpike): Is it worth rearranging this? E.g., if the number of fields + // is large enough then is it better to check for the two-byte case first? + if (static_cast(buffer_[0]) > 0) { + const uint32 kMax1ByteVarint = 0x7f; + uint32 tag = last_tag_ = buffer_[0]; + Advance(1); + return make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff); + } + // Other hot case: cutoff >= 0x80, buffer_ has at least two bytes available, + // and tag is two bytes. The latter is tested by bitwise-and-not of the + // first byte and the second byte. + if (cutoff >= 0x80 && + GOOGLE_PREDICT_TRUE(buffer_ + 1 < buffer_end_) && + GOOGLE_PREDICT_TRUE((buffer_[0] & ~buffer_[1]) >= 0x80)) { + const uint32 kMax2ByteVarint = (0x7f << 7) + 0x7f; + uint32 tag = last_tag_ = (1u << 7) * buffer_[1] + (buffer_[0] - 0x80); + Advance(2); + // It might make sense to test for tag == 0 now, but it is so rare that + // that we don't bother. A varint-encoded 0 should be one byte unless + // the encoder lost its mind. The second part of the return value of + // this function is allowed to be either true or false if the tag is 0, + // so we don't have to check for tag == 0. We may need to check whether + // it exceeds cutoff. + bool at_or_below_cutoff = cutoff >= kMax2ByteVarint || tag <= cutoff; + return make_pair(tag, at_or_below_cutoff); + } + } + // Slow path + last_tag_ = ReadTagFallback(); + return make_pair(last_tag_, static_cast(last_tag_ - 1) < cutoff); +} + inline bool CodedInputStream::LastTagWas(uint32 expected) { return last_tag_ == expected; } @@ -867,7 +981,9 @@ inline bool CodedInputStream::ExpectAtEnd() { // If we are at a limit we know no more bytes can be read. Otherwise, it's // hard to say without calling Refresh(), and we'd rather not do that. - if (buffer_ == buffer_end_ && buffer_size_after_limit_ != 0) { + if (buffer_ == buffer_end_ && + ((buffer_size_after_limit_ != 0) || + (total_bytes_read_ == current_limit_))) { last_tag_ = 0; // Pretend we called ReadTag()... legitimate_message_end_ = true; // ... and it hit EOF. return true; @@ -876,6 +992,10 @@ inline bool CodedInputStream::ExpectAtEnd() { } } +inline int CodedInputStream::CurrentPosition() const { + return total_bytes_read_ - (BufferSize() + buffer_size_after_limit_); +} + inline uint8* CodedOutputStream::GetDirectBufferForNBytesAndAdvance(int size) { if (buffer_size_ < size) { return NULL; @@ -915,8 +1035,7 @@ inline uint8* CodedOutputStream::WriteVarint32SignExtendedToArray( inline uint8* CodedOutputStream::WriteLittleEndian32ToArray(uint32 value, uint8* target) { -#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \ - defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN +#if defined(PROTOBUF_LITTLE_ENDIAN) memcpy(target, &value, sizeof(value)); #else target[0] = static_cast(value); @@ -929,8 +1048,7 @@ inline uint8* CodedOutputStream::WriteLittleEndian32ToArray(uint32 value, inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value, uint8* target) { -#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \ - defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN +#if defined(PROTOBUF_LITTLE_ENDIAN) memcpy(target, &value, sizeof(value)); #else uint32 part0 = static_cast(value); @@ -983,12 +1101,21 @@ inline int CodedOutputStream::VarintSize32SignExtended(int32 value) { } inline void CodedOutputStream::WriteString(const string& str) { - WriteRaw(str.data(), str.size()); + WriteRaw(str.data(), static_cast(str.size())); +} + +inline void CodedOutputStream::WriteRawMaybeAliased( + const void* data, int size) { + if (aliasing_enabled_) { + WriteAliasedRaw(data, size); + } else { + WriteRaw(data, size); + } } inline uint8* CodedOutputStream::WriteStringToArray( const string& str, uint8* target) { - return WriteRawToArray(str.data(), str.size(), target); + return WriteRawToArray(str.data(), static_cast(str.size()), target); } inline int CodedOutputStream::ByteCount() const { @@ -1017,7 +1144,7 @@ inline void CodedInputStream::DecrementRecursionDepth() { if (recursion_depth_ > 0) --recursion_depth_; } -inline void CodedInputStream::SetExtensionRegistry(DescriptorPool* pool, +inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool, MessageFactory* factory) { extension_pool_ = pool; extension_factory_ = factory; @@ -1031,7 +1158,7 @@ inline MessageFactory* CodedInputStream::GetExtensionFactory() { return extension_factory_; } -inline uint32 CodedInputStream::BufferSize() const { +inline int CodedInputStream::BufferSize() const { return buffer_end_ - buffer_; } @@ -1044,12 +1171,12 @@ inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input) last_tag_(0), legitimate_message_end_(false), aliasing_enabled_(false), - current_limit_(INT_MAX), + current_limit_(kint32max), buffer_size_after_limit_(0), total_bytes_limit_(kDefaultTotalBytesLimit), total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold), recursion_depth_(0), - recursion_limit_(kDefaultRecursionLimit), + recursion_limit_(default_recursion_limit_), extension_pool_(NULL), extension_factory_(NULL) { // Eagerly Refresh() so buffer space is immediately available. @@ -1070,21 +1197,24 @@ inline CodedInputStream::CodedInputStream(const uint8* buffer, int size) total_bytes_limit_(kDefaultTotalBytesLimit), total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold), recursion_depth_(0), - recursion_limit_(kDefaultRecursionLimit), + recursion_limit_(default_recursion_limit_), extension_pool_(NULL), extension_factory_(NULL) { // Note that setting current_limit_ == size is important to prevent some // code paths from trying to access input_ and segfaulting. } -inline CodedInputStream::~CodedInputStream() { - if (input_ != NULL) { - BackUpInputToCurrentPosition(); - } +inline bool CodedInputStream::IsFlat() const { + return input_ == NULL; } } // namespace io } // namespace protobuf + +#if defined(_MSC_VER) && _MSC_VER >= 1300 + #pragma runtime_checks("c", restore) +#endif // _MSC_VER + } // namespace google #endif // GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ diff --git a/src/google/protobuf/io/coded_stream_inl.h b/src/google/protobuf/io/coded_stream_inl.h index e9799d4..41dc10e 100644 --- a/src/google/protobuf/io/coded_stream_inl.h +++ b/src/google/protobuf/io/coded_stream_inl.h @@ -37,8 +37,9 @@ #define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__ #include +#include #include -#include +#include namespace google { namespace protobuf { @@ -50,8 +51,12 @@ inline bool CodedInputStream::InternalReadStringInline(string* buffer, if (BufferSize() >= size) { STLStringResizeUninitialized(buffer, size); - memcpy(string_as_array(buffer), buffer_, size); - Advance(size); + // When buffer is empty, string_as_array(buffer) will return NULL but memcpy + // requires non-NULL pointers even when size is 0. Hench this check. + if (size > 0) { + memcpy(mutable_string_data(buffer), buffer_, size); + Advance(size); + } return true; } diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc index 7d29833..0cfeb88 100644 --- a/src/google/protobuf/io/coded_stream_unittest.cc +++ b/src/google/protobuf/io/coded_stream_unittest.cc @@ -44,7 +44,6 @@ #include #include #include -#include // This declares an unsigned long long integer literal in a portable way. @@ -125,6 +124,13 @@ namespace { class CodedStreamTest : public testing::Test { protected: + // Helper method used by tests for bytes warning. See implementation comment + // for further information. + static void SetupTotalBytesLimitWarningTest( + int total_bytes_limit, int warning_threshold, + vector* out_errors, vector* out_warnings); + + // Buffer used during most of the tests. This assumes tests run sequentially. static const int kBufferSize = 1024 * 64; static uint8 buffer_[kBufferSize]; }; @@ -208,6 +214,33 @@ TEST_2D(CodedStreamTest, ReadTag, kVarintCases, kBlockSizes) { EXPECT_EQ(kVarintCases_case.size, input.ByteCount()); } +// This is the regression test that verifies that there is no issues +// with the empty input buffers handling. +TEST_F(CodedStreamTest, EmptyInputBeforeEos) { + class In : public ZeroCopyInputStream { + public: + In() : count_(0) {} + private: + virtual bool Next(const void** data, int* size) { + *data = NULL; + *size = 0; + return count_++ < 2; + } + virtual void BackUp(int count) { + GOOGLE_LOG(FATAL) << "Tests never call this."; + } + virtual bool Skip(int count) { + GOOGLE_LOG(FATAL) << "Tests never call this."; + return false; + } + virtual int64 ByteCount() const { return 0; } + int count_; + } in; + CodedInputStream input(&in); + input.ReadTag(); + EXPECT_TRUE(input.ConsumedEntireMessage()); +} + TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) { // Leave one byte at the beginning of the buffer so we can read it // to force the first buffer to be loaded. @@ -649,14 +682,197 @@ TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnHeap) { EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30)); } +TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnTotalLimit, kBlockSizes) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + coded_input.SetTotalBytesLimit(sizeof(kRawBytes), sizeof(kRawBytes)); + EXPECT_EQ(sizeof(kRawBytes), coded_input.BytesUntilTotalBytesLimit()); + + string str; + EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes))); + EXPECT_EQ(sizeof(kRawBytes) - strlen(kRawBytes), + coded_input.BytesUntilTotalBytesLimit()); + EXPECT_EQ(kRawBytes, str); + // TODO(liujisi): Replace with a more meaningful test (see cl/60966023). + EXPECT_GE(str.capacity(), strlen(kRawBytes)); + } + + EXPECT_EQ(strlen(kRawBytes), input.ByteCount()); +} + +TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnPushedLimit, kBlockSizes) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + coded_input.PushLimit(sizeof(buffer_)); + + string str; + EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes))); + EXPECT_EQ(kRawBytes, str); + // TODO(liujisi): Replace with a more meaningful test (see cl/60966023). + EXPECT_GE(str.capacity(), strlen(kRawBytes)); + } + + EXPECT_EQ(strlen(kRawBytes), input.ByteCount()); +} + +TEST_F(CodedStreamTest, ReadStringNoReservationIfLimitsNotSet) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + + string str; + EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes))); + EXPECT_EQ(kRawBytes, str); + // Note: this check depends on string class implementation. It + // expects that string will allocate more than strlen(kRawBytes) + // if the content of kRawBytes is appended to string in small + // chunks. + // TODO(liujisi): Replace with a more meaningful test (see cl/60966023). + EXPECT_GE(str.capacity(), strlen(kRawBytes)); + } + + EXPECT_EQ(strlen(kRawBytes), input.ByteCount()); +} + +TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsNegative) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + coded_input.PushLimit(sizeof(buffer_)); + + string str; + EXPECT_FALSE(coded_input.ReadString(&str, -1)); + // Note: this check depends on string class implementation. It + // expects that string will always allocate the same amount of + // memory for an empty string. + EXPECT_EQ(string().capacity(), str.capacity()); + } +} + +TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsLarge) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + coded_input.PushLimit(sizeof(buffer_)); + + string str; + EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30)); + EXPECT_GT(1 << 30, str.capacity()); + } +} + +TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsOverTheLimit) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + coded_input.PushLimit(16); + + string str; + EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes))); + // Note: this check depends on string class implementation. It + // expects that string will allocate less than strlen(kRawBytes) + // for an empty string. + EXPECT_GT(strlen(kRawBytes), str.capacity()); + } +} + +TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsOverTheTotalBytesLimit) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + coded_input.SetTotalBytesLimit(16, 16); + + string str; + EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes))); + // Note: this check depends on string class implementation. It + // expects that string will allocate less than strlen(kRawBytes) + // for an empty string. + EXPECT_GT(strlen(kRawBytes), str.capacity()); + } +} + +TEST_F(CodedStreamTest, + ReadStringNoReservationSizeIsOverTheClosestLimit_GlobalLimitIsCloser) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + coded_input.PushLimit(sizeof(buffer_)); + coded_input.SetTotalBytesLimit(16, 16); + + string str; + EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes))); + // Note: this check depends on string class implementation. It + // expects that string will allocate less than strlen(kRawBytes) + // for an empty string. + EXPECT_GT(strlen(kRawBytes), str.capacity()); + } +} + +TEST_F(CodedStreamTest, + ReadStringNoReservationSizeIsOverTheClosestLimit_LocalLimitIsCloser) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + coded_input.PushLimit(16); + coded_input.SetTotalBytesLimit(sizeof(buffer_), sizeof(buffer_)); + EXPECT_EQ(sizeof(buffer_), coded_input.BytesUntilTotalBytesLimit()); + + string str; + EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes))); + // Note: this check depends on string class implementation. It + // expects that string will allocate less than strlen(kRawBytes) + // for an empty string. + EXPECT_GT(strlen(kRawBytes), str.capacity()); + } +} + // ------------------------------------------------------------------- // Skip const char kSkipTestBytes[] = ""; -const char kSkipOutputTestBytes[] = - "---------------------------------"; TEST_1D(CodedStreamTest, SkipInput, kBlockSizes) { memcpy(buffer_, kSkipTestBytes, sizeof(kSkipTestBytes)); @@ -947,9 +1163,11 @@ TEST_F(CodedStreamTest, TotalBytesLimit) { ArrayInputStream input(buffer_, sizeof(buffer_)); CodedInputStream coded_input(&input); coded_input.SetTotalBytesLimit(16, -1); + EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit()); string str; EXPECT_TRUE(coded_input.ReadString(&str, 16)); + EXPECT_EQ(0, coded_input.BytesUntilTotalBytesLimit()); vector errors; @@ -964,7 +1182,9 @@ TEST_F(CodedStreamTest, TotalBytesLimit) { "A protocol message was rejected because it was too big", errors[0]); coded_input.SetTotalBytesLimit(32, -1); + EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit()); EXPECT_TRUE(coded_input.ReadString(&str, 16)); + EXPECT_EQ(0, coded_input.BytesUntilTotalBytesLimit()); } TEST_F(CodedStreamTest, TotalBytesLimitNotValidMessageEnd) { @@ -995,6 +1215,60 @@ TEST_F(CodedStreamTest, TotalBytesLimitNotValidMessageEnd) { EXPECT_FALSE(coded_input.ConsumedEntireMessage()); } +// This method is used by the tests below. +// It constructs a CodedInputStream with the given limits and tries to read 2KiB +// of data from it. Then it returns the logged errors and warnings in the given +// vectors. +void CodedStreamTest::SetupTotalBytesLimitWarningTest( + int total_bytes_limit, int warning_threshold, + vector* out_errors, vector* out_warnings) { + ArrayInputStream raw_input(buffer_, sizeof(buffer_), 128); + + ScopedMemoryLog scoped_log; + { + CodedInputStream input(&raw_input); + input.SetTotalBytesLimit(total_bytes_limit, warning_threshold); + string str; + EXPECT_TRUE(input.ReadString(&str, 2048)); + } + + *out_errors = scoped_log.GetMessages(ERROR); + *out_warnings = scoped_log.GetMessages(WARNING); +} + +TEST_F(CodedStreamTest, TotalBytesLimitWarning) { + vector errors; + vector warnings; + SetupTotalBytesLimitWarningTest(10240, 1024, &errors, &warnings); + + EXPECT_EQ(0, errors.size()); + + ASSERT_EQ(2, warnings.size()); + EXPECT_PRED_FORMAT2(testing::IsSubstring, + "Reading dangerously large protocol message. If the message turns out to " + "be larger than 10240 bytes, parsing will be halted for security reasons.", + warnings[0]); + EXPECT_PRED_FORMAT2(testing::IsSubstring, + "The total number of bytes read was 2048", + warnings[1]); +} + +TEST_F(CodedStreamTest, TotalBytesLimitWarningDisabled) { + vector errors; + vector warnings; + + // Test with -1 + SetupTotalBytesLimitWarningTest(10240, -1, &errors, &warnings); + EXPECT_EQ(0, errors.size()); + EXPECT_EQ(0, warnings.size()); + + // Test again with -2, expecting the same result + SetupTotalBytesLimitWarningTest(10240, -2, &errors, &warnings); + EXPECT_EQ(0, errors.size()); + EXPECT_EQ(0, warnings.size()); +} + + TEST_F(CodedStreamTest, RecursionLimit) { ArrayInputStream input(buffer_, sizeof(buffer_)); CodedInputStream coded_input(&input); @@ -1032,6 +1306,7 @@ TEST_F(CodedStreamTest, RecursionLimit) { EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 7 } + class ReallyBigInputStream : public ZeroCopyInputStream { public: ReallyBigInputStream() : backup_amount_(0), buffer_count_(0) {} diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc index 84d277f..fe1f331 100644 --- a/src/google/protobuf/io/gzip_stream.cc +++ b/src/google/protobuf/io/gzip_stream.cc @@ -73,6 +73,17 @@ GzipInputStream::~GzipInputStream() { zerror_ = inflateEnd(&zcontext_); } +static inline int internalInflateInit2( + z_stream* zcontext, GzipInputStream::Format format) { + int windowBitsFormat = 0; + switch (format) { + case GzipInputStream::GZIP: windowBitsFormat = 16; break; + case GzipInputStream::AUTO: windowBitsFormat = 32; break; + case GzipInputStream::ZLIB: windowBitsFormat = 0; break; + } + return inflateInit2(zcontext, /* windowBits */15 | windowBitsFormat); +} + int GzipInputStream::Inflate(int flush) { if ((zerror_ == Z_OK) && (zcontext_.avail_out == 0)) { // previous inflate filled output buffer. don't change input params yet. @@ -89,14 +100,7 @@ int GzipInputStream::Inflate(int flush) { zcontext_.next_in = static_cast(const_cast(in)); zcontext_.avail_in = in_size; if (first) { - int windowBitsFormat = 0; - switch (format_) { - case GZIP: windowBitsFormat = 16; break; - case AUTO: windowBitsFormat = 32; break; - case ZLIB: windowBitsFormat = 0; break; - } - int error = inflateInit2(&zcontext_, - /* windowBits */15 | windowBitsFormat); + int error = internalInflateInit2(&zcontext_, format_); if (error != Z_OK) { return error; } @@ -127,9 +131,21 @@ bool GzipInputStream::Next(const void** data, int* size) { return true; } if (zerror_ == Z_STREAM_END) { - *data = NULL; - *size = 0; - return false; + if (zcontext_.next_out != NULL) { + // sub_stream_ may have concatenated streams to follow + zerror_ = inflateEnd(&zcontext_); + if (zerror_ != Z_OK) { + return false; + } + zerror_ = internalInflateInit2(&zcontext_, format_); + if (zerror_ != Z_OK) { + return false; + } + } else { + *data = NULL; + *size = 0; + return false; + } } zerror_ = Inflate(Z_NO_FLUSH); if ((zerror_ == Z_STREAM_END) && (zcontext_.next_out == NULL)) { @@ -183,16 +199,6 @@ GzipOutputStream::GzipOutputStream(ZeroCopyOutputStream* sub_stream, Init(sub_stream, options); } -GzipOutputStream::GzipOutputStream( - ZeroCopyOutputStream* sub_stream, Format format, int buffer_size) { - Options options; - options.format = format; - if (buffer_size != -1) { - options.buffer_size = buffer_size; - } - Init(sub_stream, options); -} - void GzipOutputStream::Init(ZeroCopyOutputStream* sub_stream, const Options& options) { sub_stream_ = sub_stream; @@ -251,8 +257,7 @@ int GzipOutputStream::Deflate(int flush) { } error = deflate(&zcontext_, flush); } while (error == Z_OK && zcontext_.avail_out == 0); - if (((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) - && (zcontext_.avail_out != sub_data_size_)) { + if ((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) { // Notify lower layer of data. sub_stream_->BackUp(zcontext_.avail_out); // We don't own the buffer anymore. @@ -294,10 +299,11 @@ int64 GzipOutputStream::ByteCount() const { } bool GzipOutputStream::Flush() { - do { - zerror_ = Deflate(Z_FULL_FLUSH); - } while (zerror_ == Z_OK); - return zerror_ == Z_OK; + zerror_ = Deflate(Z_FULL_FLUSH); + // Return true if the flush succeeded or if it was a no-op. + return (zerror_ == Z_OK) || + (zerror_ == Z_BUF_ERROR && zcontext_.avail_in == 0 && + zcontext_.avail_out != 0); } bool GzipOutputStream::Close() { diff --git a/src/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h index 65dbc5b..7ee24bc 100644 --- a/src/google/protobuf/io/gzip_stream.h +++ b/src/google/protobuf/io/gzip_stream.h @@ -45,6 +45,7 @@ #include +#include #include namespace google { @@ -144,12 +145,6 @@ class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream { ZeroCopyOutputStream* sub_stream, const Options& options); - // DEPRECATED: Use one of the above constructors instead. - GzipOutputStream( - ZeroCopyOutputStream* sub_stream, - Format format, - int buffer_size = -1) GOOGLE_ATTRIBUTE_DEPRECATED; - virtual ~GzipOutputStream(); // Return last error message or NULL if no error. @@ -165,6 +160,13 @@ class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream { // necessary. // Compression may be less efficient stopping and starting around flushes. // Returns true if no error. + // + // Please ensure that block size is > 6. Here is an excerpt from the zlib + // doc that explains why: + // + // In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out + // is greater than six to avoid repeated flush markers due to + // avail_out == 0 on return. bool Flush(); // Writes out all data and closes the gzip stream. diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc index c7d3074..d2bf3f5 100644 --- a/src/google/protobuf/io/printer.cc +++ b/src/google/protobuf/io/printer.cc @@ -35,7 +35,6 @@ #include #include #include -#include namespace google { namespace protobuf { @@ -51,8 +50,8 @@ Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter) } Printer::~Printer() { - // Only BackUp() if we're sure we've successfully called Next() at least once. - if (buffer_size_ > 0) { + // Only BackUp() if we have called Next() at least once and never failed. + if (buffer_size_ > 0 && !failed_) { output_->BackUp(buffer_size_); } } @@ -132,6 +131,17 @@ void Printer::Print(const char* text, Print(vars, text); } +void Printer::Print(const char* text, + const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3) { + map vars; + vars[variable1] = value1; + vars[variable2] = value2; + vars[variable3] = value3; + Print(vars, text); +} + void Printer::Indent() { indent_ += " "; } @@ -158,7 +168,7 @@ void Printer::WriteRaw(const char* data, int size) { if (failed_) return; if (size == 0) return; - if (at_start_of_line_) { + if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) { // Insert an indent. at_start_of_line_ = false; WriteRaw(indent_.data(), indent_.size()); diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h index de08538..5be4854 100644 --- a/src/google/protobuf/io/printer.h +++ b/src/google/protobuf/io/printer.h @@ -82,7 +82,11 @@ class LIBPROTOBUF_EXPORT Printer { // Like the first Print(), except the substitutions are given as parameters. void Print(const char* text, const char* variable1, const string& value1, const char* variable2, const string& value2); - // TODO(kenton): Overloaded versions with more variables? Two seems + // Like the first Print(), except the substitutions are given as parameters. + void Print(const char* text, const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3); + // TODO(kenton): Overloaded versions with more variables? Three seems // to be enough. // Indent text by two spaces. After calling Indent(), two spaces will be diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc index 580a53d..76fb944 100644 --- a/src/google/protobuf/io/printer_unittest.cc +++ b/src/google/protobuf/io/printer_unittest.cc @@ -220,7 +220,7 @@ TEST(Printer, Indenting) { } // Death tests do not work on Windows as of yet. -#ifdef GTEST_HAS_DEATH_TEST +#ifdef PROTOBUF_HAS_DEATH_TEST TEST(Printer, Death) { char buffer[8192]; @@ -231,9 +231,33 @@ TEST(Printer, Death) { EXPECT_DEBUG_DEATH(printer.Print("$unclosed"), "Unclosed variable name"); EXPECT_DEBUG_DEATH(printer.Outdent(), "without matching Indent"); } -#endif // GTEST_HAS_DEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST -TEST(Printer, WriteFailure) { +TEST(Printer, WriteFailurePartial) { + char buffer[17]; + + ArrayOutputStream output(buffer, sizeof(buffer)); + Printer printer(&output, '$'); + + // Print 16 bytes to almost fill the buffer (should not fail). + printer.Print("0123456789abcdef"); + EXPECT_FALSE(printer.failed()); + + // Try to print 2 chars. Only one fits. + printer.Print("<>"); + EXPECT_TRUE(printer.failed()); + + // Anything else should fail too. + printer.Print(" "); + EXPECT_TRUE(printer.failed()); + printer.Print("blah"); + EXPECT_TRUE(printer.failed()); + + // Buffer should contain the first 17 bytes written. + EXPECT_EQ("0123456789abcdef<", string(buffer, sizeof(buffer))); +} + +TEST(Printer, WriteFailureExact) { char buffer[16]; ArrayOutputStream output(buffer, sizeof(buffer)); diff --git a/src/google/protobuf/io/strtod.cc b/src/google/protobuf/io/strtod.cc new file mode 100644 index 0000000..cf0c6e1 --- /dev/null +++ b/src/google/protobuf/io/strtod.cc @@ -0,0 +1,113 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +#include + +#include +#include +#include + +#include + +namespace google { +namespace protobuf { +namespace io { + +// ---------------------------------------------------------------------- +// NoLocaleStrtod() +// This code will make you cry. +// ---------------------------------------------------------------------- + +namespace { + +// Returns a string identical to *input except that the character pointed to +// by radix_pos (which should be '.') is replaced with the locale-specific +// radix character. +string LocalizeRadix(const char* input, const char* radix_pos) { + // Determine the locale-specific radix character by calling sprintf() to + // print the number 1.5, then stripping off the digits. As far as I can + // tell, this is the only portable, thread-safe way to get the C library + // to divuldge the locale's radix character. No, localeconv() is NOT + // thread-safe. + char temp[16]; + int size = sprintf(temp, "%.1f", 1.5); + GOOGLE_CHECK_EQ(temp[0], '1'); + GOOGLE_CHECK_EQ(temp[size-1], '5'); + GOOGLE_CHECK_LE(size, 6); + + // Now replace the '.' in the input with it. + string result; + result.reserve(strlen(input) + size - 3); + result.append(input, radix_pos); + result.append(temp + 1, size - 2); + result.append(radix_pos + 1); + return result; +} + +} // namespace + +double NoLocaleStrtod(const char* text, char** original_endptr) { + // We cannot simply set the locale to "C" temporarily with setlocale() + // as this is not thread-safe. Instead, we try to parse in the current + // locale first. If parsing stops at a '.' character, then this is a + // pretty good hint that we're actually in some other locale in which + // '.' is not the radix character. + + char* temp_endptr; + double result = strtod(text, &temp_endptr); + if (original_endptr != NULL) *original_endptr = temp_endptr; + if (*temp_endptr != '.') return result; + + // Parsing halted on a '.'. Perhaps we're in a different locale? Let's + // try to replace the '.' with a locale-specific radix character and + // try again. + string localized = LocalizeRadix(text, temp_endptr); + const char* localized_cstr = localized.c_str(); + char* localized_endptr; + result = strtod(localized_cstr, &localized_endptr); + if ((localized_endptr - localized_cstr) > + (temp_endptr - text)) { + // This attempt got further, so replacing the decimal must have helped. + // Update original_endptr to point at the right location. + if (original_endptr != NULL) { + // size_diff is non-zero if the localized radix has multiple bytes. + int size_diff = localized.size() - strlen(text); + // const_cast is necessary to match the strtod() interface. + *original_endptr = const_cast( + text + (localized_endptr - localized_cstr - size_diff)); + } + } + + return result; +} + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/io/strtod.h b/src/google/protobuf/io/strtod.h new file mode 100644 index 0000000..2be3c43 --- /dev/null +++ b/src/google/protobuf/io/strtod.h @@ -0,0 +1,50 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// A locale-independent version of strtod(), used to parse floating +// point default values in .proto files, where the decimal separator +// is always a dot. + +#ifndef GOOGLE_PROTOBUF_IO_STRTOD_H__ +#define GOOGLE_PROTOBUF_IO_STRTOD_H__ + +namespace google { +namespace protobuf { +namespace io { + +// A locale-independent version of the standard strtod(), which always +// uses a dot as the decimal separator. +double NoLocaleStrtod(const char* str, char** endptr); + +} // namespace io +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_IO_STRTOD_H__ diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc index 38fa351..d149305 100644 --- a/src/google/protobuf/io/tokenizer.cc +++ b/src/google/protobuf/io/tokenizer.cc @@ -89,8 +89,12 @@ // exactly pretty. #include +#include +#include +#include #include #include +#include namespace google { namespace protobuf { @@ -118,6 +122,8 @@ namespace { CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\v' || c == '\f'); +CHARACTER_CLASS(WhitespaceNoNewline, c == ' ' || c == '\t' || + c == '\r' || c == '\v' || c == '\f'); CHARACTER_CLASS(Unprintable, c < ' ' && c > '\0'); @@ -187,12 +193,16 @@ Tokenizer::Tokenizer(ZeroCopyInputStream* input, read_error_(false), line_(0), column_(0), - token_start_(-1), + record_target_(NULL), + record_start_(-1), allow_f_after_float_(false), - comment_style_(CPP_COMMENT_STYLE) { + comment_style_(CPP_COMMENT_STYLE), + require_space_after_number_(true), + allow_multiline_strings_(false) { current_.line = 0; current_.column = 0; + current_.end_column = 0; current_.type = TYPE_START; Refresh(); @@ -237,9 +247,9 @@ void Tokenizer::Refresh() { } // If we're in a token, append the rest of the buffer to it. - if (token_start_ >= 0 && token_start_ < buffer_size_) { - current_.text.append(buffer_ + token_start_, buffer_size_ - token_start_); - token_start_ = 0; + if (record_target_ != NULL && record_start_ < buffer_size_) { + record_target_->append(buffer_ + record_start_, buffer_size_ - record_start_); + record_start_ = 0; } const void* data = NULL; @@ -260,23 +270,34 @@ void Tokenizer::Refresh() { current_char_ = buffer_[0]; } +inline void Tokenizer::RecordTo(string* target) { + record_target_ = target; + record_start_ = buffer_pos_; +} + +inline void Tokenizer::StopRecording() { + // Note: The if() is necessary because some STL implementations crash when + // you call string::append(NULL, 0), presumably because they are trying to + // be helpful by detecting the NULL pointer, even though there's nothing + // wrong with reading zero bytes from NULL. + if (buffer_pos_ != record_start_) { + record_target_->append(buffer_ + record_start_, buffer_pos_ - record_start_); + } + record_target_ = NULL; + record_start_ = -1; +} + inline void Tokenizer::StartToken() { - token_start_ = buffer_pos_; current_.type = TYPE_START; // Just for the sake of initializing it. current_.text.clear(); current_.line = line_; current_.column = column_; + RecordTo(¤t_.text); } inline void Tokenizer::EndToken() { - // Note: The if() is necessary because some STL implementations crash when - // you call string::append(NULL, 0), presumably because they are trying to - // be helpful by detecting the NULL pointer, even though there's nothing - // wrong with reading zero bytes from NULL. - if (buffer_pos_ != token_start_) { - current_.text.append(buffer_ + token_start_, buffer_pos_ - token_start_); - } - token_start_ = -1; + StopRecording(); + current_.end_column = column_; } // ------------------------------------------------------------------- @@ -332,9 +353,16 @@ void Tokenizer::ConsumeString(char delimiter) { while (true) { switch (current_char_) { case '\0': - case '\n': { - AddError("String literals cannot cross line boundaries."); + AddError("Unexpected end of string."); return; + + case '\n': { + if (!allow_multiline_strings_) { + AddError("String literals cannot cross line boundaries."); + return; + } + NextChar(); + break; } case '\\': { @@ -351,6 +379,27 @@ void Tokenizer::ConsumeString(char delimiter) { AddError("Expected hex digits for escape sequence."); } // Possibly followed by another hex digit, but again we don't care. + } else if (TryConsume('u')) { + if (!TryConsumeOne() || + !TryConsumeOne() || + !TryConsumeOne() || + !TryConsumeOne()) { + AddError("Expected four hex digits for \\u escape sequence."); + } + } else if (TryConsume('U')) { + // We expect 8 hex digits; but only the range up to 0x10ffff is + // legal. + if (!TryConsume('0') || + !TryConsume('0') || + !(TryConsume('0') || TryConsume('1')) || + !TryConsumeOne() || + !TryConsumeOne() || + !TryConsumeOne() || + !TryConsumeOne() || + !TryConsumeOne()) { + AddError("Expected eight hex digits up to 10ffff for \\U escape " + "sequence"); + } } else { AddError("Invalid escape sequence in string literal."); } @@ -410,7 +459,7 @@ Tokenizer::TokenType Tokenizer::ConsumeNumber(bool started_with_zero, } } - if (LookingAt()) { + if (LookingAt() && require_space_after_number_) { AddError("Need space between number and identifier."); } else if (current_char_ == '.') { if (is_float) { @@ -424,26 +473,51 @@ Tokenizer::TokenType Tokenizer::ConsumeNumber(bool started_with_zero, return is_float ? TYPE_FLOAT : TYPE_INTEGER; } -void Tokenizer::ConsumeLineComment() { +void Tokenizer::ConsumeLineComment(string* content) { + if (content != NULL) RecordTo(content); + while (current_char_ != '\0' && current_char_ != '\n') { NextChar(); } TryConsume('\n'); + + if (content != NULL) StopRecording(); } -void Tokenizer::ConsumeBlockComment() { +void Tokenizer::ConsumeBlockComment(string* content) { int start_line = line_; int start_column = column_ - 2; + if (content != NULL) RecordTo(content); + while (true) { while (current_char_ != '\0' && current_char_ != '*' && - current_char_ != '/') { + current_char_ != '/' && + current_char_ != '\n') { NextChar(); } - if (TryConsume('*') && TryConsume('/')) { + if (TryConsume('\n')) { + if (content != NULL) StopRecording(); + + // Consume leading whitespace and asterisk; + ConsumeZeroOrMore(); + if (TryConsume('*')) { + if (TryConsume('/')) { + // End of comment. + break; + } + } + + if (content != NULL) RecordTo(content); + } else if (TryConsume('*') && TryConsume('/')) { // End of comment. + if (content != NULL) { + StopRecording(); + // Strip trailing "*/". + content->erase(content->size() - 2); + } break; } else if (TryConsume('/') && current_char_ == '*') { // Note: We didn't consume the '*' because if there is a '/' after it @@ -454,42 +528,59 @@ void Tokenizer::ConsumeBlockComment() { AddError("End-of-file inside block comment."); error_collector_->AddError( start_line, start_column, " Comment started here."); + if (content != NULL) StopRecording(); break; } } } +Tokenizer::NextCommentStatus Tokenizer::TryConsumeCommentStart() { + if (comment_style_ == CPP_COMMENT_STYLE && TryConsume('/')) { + if (TryConsume('/')) { + return LINE_COMMENT; + } else if (TryConsume('*')) { + return BLOCK_COMMENT; + } else { + // Oops, it was just a slash. Return it. + current_.type = TYPE_SYMBOL; + current_.text = "/"; + current_.line = line_; + current_.column = column_ - 1; + current_.end_column = column_; + return SLASH_NOT_COMMENT; + } + } else if (comment_style_ == SH_COMMENT_STYLE && TryConsume('#')) { + return LINE_COMMENT; + } else { + return NO_COMMENT; + } +} + // ------------------------------------------------------------------- bool Tokenizer::Next() { - TokenType last_token_type = current_.type; - - // Did we skip any characters after the last token? - bool skipped_stuff = false; + previous_ = current_; while (!read_error_) { - if (TryConsumeOne()) { - ConsumeZeroOrMore(); - - } else if (comment_style_ == CPP_COMMENT_STYLE && TryConsume('/')) { - // Starting a comment? - if (TryConsume('/')) { - ConsumeLineComment(); - } else if (TryConsume('*')) { - ConsumeBlockComment(); - } else { - // Oops, it was just a slash. Return it. - current_.type = TYPE_SYMBOL; - current_.text = "/"; - current_.line = line_; - current_.column = column_ - 1; + ConsumeZeroOrMore(); + + switch (TryConsumeCommentStart()) { + case LINE_COMMENT: + ConsumeLineComment(NULL); + continue; + case BLOCK_COMMENT: + ConsumeBlockComment(NULL); + continue; + case SLASH_NOT_COMMENT: return true; - } + case NO_COMMENT: + break; + } - } else if (comment_style_ == SH_COMMENT_STYLE && TryConsume('#')) { - ConsumeLineComment(); + // Check for EOF before continuing. + if (read_error_) break; - } else if (LookingAt() || current_char_ == '\0') { + if (LookingAt() || current_char_ == '\0') { AddError("Invalid control characters encountered in text."); NextChar(); // Skip more unprintable characters, too. But, remember that '\0' is @@ -517,7 +608,9 @@ bool Tokenizer::Next() { if (TryConsumeOne()) { // It's a floating-point number. - if (last_token_type == TYPE_IDENTIFIER && !skipped_stuff) { + if (previous_.type == TYPE_IDENTIFIER && + current_.line == previous_.line && + current_.column == previous_.end_column) { // We don't accept syntax like "blah.123". error_collector_->AddError(line_, column_ - 2, "Need space between identifier and decimal point."); @@ -535,6 +628,12 @@ bool Tokenizer::Next() { ConsumeString('\''); current_.type = TYPE_STRING; } else { + // Check if the high order bit is set. + if (current_char_ & 0x80) { + error_collector_->AddError(line_, column_, + StringPrintf("Interpreting non ascii codepoint %d.", + static_cast(current_char_))); + } NextChar(); current_.type = TYPE_SYMBOL; } @@ -542,8 +641,6 @@ bool Tokenizer::Next() { EndToken(); return true; } - - skipped_stuff = true; } // EOF @@ -551,9 +648,199 @@ bool Tokenizer::Next() { current_.text.clear(); current_.line = line_; current_.column = column_; + current_.end_column = column_; return false; } +namespace { + +// Helper class for collecting comments and putting them in the right places. +// +// This basically just buffers the most recent comment until it can be decided +// exactly where that comment should be placed. When Flush() is called, the +// current comment goes into either prev_trailing_comments or detached_comments. +// When the CommentCollector is destroyed, the last buffered comment goes into +// next_leading_comments. +class CommentCollector { + public: + CommentCollector(string* prev_trailing_comments, + vector* detached_comments, + string* next_leading_comments) + : prev_trailing_comments_(prev_trailing_comments), + detached_comments_(detached_comments), + next_leading_comments_(next_leading_comments), + has_comment_(false), + is_line_comment_(false), + can_attach_to_prev_(true) { + if (prev_trailing_comments != NULL) prev_trailing_comments->clear(); + if (detached_comments != NULL) detached_comments->clear(); + if (next_leading_comments != NULL) next_leading_comments->clear(); + } + + ~CommentCollector() { + // Whatever is in the buffer is a leading comment. + if (next_leading_comments_ != NULL && has_comment_) { + comment_buffer_.swap(*next_leading_comments_); + } + } + + // About to read a line comment. Get the comment buffer pointer in order to + // read into it. + string* GetBufferForLineComment() { + // We want to combine with previous line comments, but not block comments. + if (has_comment_ && !is_line_comment_) { + Flush(); + } + has_comment_ = true; + is_line_comment_ = true; + return &comment_buffer_; + } + + // About to read a block comment. Get the comment buffer pointer in order to + // read into it. + string* GetBufferForBlockComment() { + if (has_comment_) { + Flush(); + } + has_comment_ = true; + is_line_comment_ = false; + return &comment_buffer_; + } + + void ClearBuffer() { + comment_buffer_.clear(); + has_comment_ = false; + } + + // Called once we know that the comment buffer is complete and is *not* + // connected to the next token. + void Flush() { + if (has_comment_) { + if (can_attach_to_prev_) { + if (prev_trailing_comments_ != NULL) { + prev_trailing_comments_->append(comment_buffer_); + } + can_attach_to_prev_ = false; + } else { + if (detached_comments_ != NULL) { + detached_comments_->push_back(comment_buffer_); + } + } + ClearBuffer(); + } + } + + void DetachFromPrev() { + can_attach_to_prev_ = false; + } + + private: + string* prev_trailing_comments_; + vector* detached_comments_; + string* next_leading_comments_; + + string comment_buffer_; + + // True if any comments were read into comment_buffer_. This can be true even + // if comment_buffer_ is empty, namely if the comment was "/**/". + bool has_comment_; + + // Is the comment in the comment buffer a line comment? + bool is_line_comment_; + + // Is it still possible that we could be reading a comment attached to the + // previous token? + bool can_attach_to_prev_; +}; + +} // namespace + +bool Tokenizer::NextWithComments(string* prev_trailing_comments, + vector* detached_comments, + string* next_leading_comments) { + CommentCollector collector(prev_trailing_comments, detached_comments, + next_leading_comments); + + if (current_.type == TYPE_START) { + collector.DetachFromPrev(); + } else { + // A comment appearing on the same line must be attached to the previous + // declaration. + ConsumeZeroOrMore(); + switch (TryConsumeCommentStart()) { + case LINE_COMMENT: + ConsumeLineComment(collector.GetBufferForLineComment()); + + // Don't allow comments on subsequent lines to be attached to a trailing + // comment. + collector.Flush(); + break; + case BLOCK_COMMENT: + ConsumeBlockComment(collector.GetBufferForBlockComment()); + + ConsumeZeroOrMore(); + if (!TryConsume('\n')) { + // Oops, the next token is on the same line. If we recorded a comment + // we really have no idea which token it should be attached to. + collector.ClearBuffer(); + return Next(); + } + + // Don't allow comments on subsequent lines to be attached to a trailing + // comment. + collector.Flush(); + break; + case SLASH_NOT_COMMENT: + return true; + case NO_COMMENT: + if (!TryConsume('\n')) { + // The next token is on the same line. There are no comments. + return Next(); + } + break; + } + } + + // OK, we are now on the line *after* the previous token. + while (true) { + ConsumeZeroOrMore(); + + switch (TryConsumeCommentStart()) { + case LINE_COMMENT: + ConsumeLineComment(collector.GetBufferForLineComment()); + break; + case BLOCK_COMMENT: + ConsumeBlockComment(collector.GetBufferForBlockComment()); + + // Consume the rest of the line so that we don't interpret it as a + // blank line the next time around the loop. + ConsumeZeroOrMore(); + TryConsume('\n'); + break; + case SLASH_NOT_COMMENT: + return true; + case NO_COMMENT: + if (TryConsume('\n')) { + // Completely blank line. + collector.Flush(); + collector.DetachFromPrev(); + } else { + bool result = Next(); + if (!result || + current_.text == "}" || + current_.text == "]" || + current_.text == ")") { + // It looks like we're at the end of a scope. In this case it + // makes no sense to attach a comment to the following token. + collector.Flush(); + } + return result; + } + break; + } + } +} + // ------------------------------------------------------------------- // Token-parsing helpers. Remember that these don't need to report // errors since any errors should already have been reported while @@ -623,17 +910,138 @@ double Tokenizer::ParseFloat(const string& text) { return result; } +// Helper to append a Unicode code point to a string as UTF8, without bringing +// in any external dependencies. +static void AppendUTF8(uint32 code_point, string* output) { + uint32 tmp = 0; + int len = 0; + if (code_point <= 0x7f) { + tmp = code_point; + len = 1; + } else if (code_point <= 0x07ff) { + tmp = 0x0000c080 | + ((code_point & 0x07c0) << 2) | + (code_point & 0x003f); + len = 2; + } else if (code_point <= 0xffff) { + tmp = 0x00e08080 | + ((code_point & 0xf000) << 4) | + ((code_point & 0x0fc0) << 2) | + (code_point & 0x003f); + len = 3; + } else if (code_point <= 0x1fffff) { + tmp = 0xf0808080 | + ((code_point & 0x1c0000) << 6) | + ((code_point & 0x03f000) << 4) | + ((code_point & 0x000fc0) << 2) | + (code_point & 0x003f); + len = 4; + } else { + // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is + // normally only defined up to there as well. + StringAppendF(output, "\\U%08x", code_point); + return; + } + tmp = ghtonl(tmp); + output->append(reinterpret_cast(&tmp) + sizeof(tmp) - len, len); +} + +// Try to read hex digits from ptr, and stuff the numeric result into +// *result. Returns true if that many digits were successfully consumed. +static bool ReadHexDigits(const char* ptr, int len, uint32* result) { + *result = 0; + if (len == 0) return false; + for (const char* end = ptr + len; ptr < end; ++ptr) { + if (*ptr == '\0') return false; + *result = (*result << 4) + DigitValue(*ptr); + } + return true; +} + +// Handling UTF-16 surrogate pairs. UTF-16 encodes code points in the range +// 0x10000...0x10ffff as a pair of numbers, a head surrogate followed by a trail +// surrogate. These numbers are in a reserved range of Unicode code points, so +// if we encounter such a pair we know how to parse it and convert it into a +// single code point. +static const uint32 kMinHeadSurrogate = 0xd800; +static const uint32 kMaxHeadSurrogate = 0xdc00; +static const uint32 kMinTrailSurrogate = 0xdc00; +static const uint32 kMaxTrailSurrogate = 0xe000; + +static inline bool IsHeadSurrogate(uint32 code_point) { + return (code_point >= kMinHeadSurrogate) && (code_point < kMaxHeadSurrogate); +} + +static inline bool IsTrailSurrogate(uint32 code_point) { + return (code_point >= kMinTrailSurrogate) && + (code_point < kMaxTrailSurrogate); +} + +// Combine a head and trail surrogate into a single Unicode code point. +static uint32 AssembleUTF16(uint32 head_surrogate, uint32 trail_surrogate) { + GOOGLE_DCHECK(IsHeadSurrogate(head_surrogate)); + GOOGLE_DCHECK(IsTrailSurrogate(trail_surrogate)); + return 0x10000 + (((head_surrogate - kMinHeadSurrogate) << 10) | + (trail_surrogate - kMinTrailSurrogate)); +} + +// Convert the escape sequence parameter to a number of expected hex digits. +static inline int UnicodeLength(char key) { + if (key == 'u') return 4; + if (key == 'U') return 8; + return 0; +} + +// Given a pointer to the 'u' or 'U' starting a Unicode escape sequence, attempt +// to parse that sequence. On success, returns a pointer to the first char +// beyond that sequence, and fills in *code_point. On failure, returns ptr +// itself. +static const char* FetchUnicodePoint(const char* ptr, uint32* code_point) { + const char* p = ptr; + // Fetch the code point. + const int len = UnicodeLength(*p++); + if (!ReadHexDigits(p, len, code_point)) + return ptr; + p += len; + + // Check if the code point we read is a "head surrogate." If so, then we + // expect it to be immediately followed by another code point which is a valid + // "trail surrogate," and together they form a UTF-16 pair which decodes into + // a single Unicode point. Trail surrogates may only use \u, not \U. + if (IsHeadSurrogate(*code_point) && *p == '\\' && *(p + 1) == 'u') { + uint32 trail_surrogate; + if (ReadHexDigits(p + 2, 4, &trail_surrogate) && + IsTrailSurrogate(trail_surrogate)) { + *code_point = AssembleUTF16(*code_point, trail_surrogate); + p += 6; + } + // If this failed, then we just emit the head surrogate as a code point. + // It's bogus, but so is the string. + } + + return p; +} + +// The text string must begin and end with single or double quote +// characters. void Tokenizer::ParseStringAppend(const string& text, string* output) { - // Reminder: text[0] is always the quote character. (If text is - // empty, it's invalid, so we'll just return.) - if (text.empty()) { + // Reminder: text[0] is always a quote character. (If text is + // empty, it's invalid, so we'll just return). + const size_t text_size = text.size(); + if (text_size == 0) { GOOGLE_LOG(DFATAL) << " Tokenizer::ParseStringAppend() passed text that could not" " have been tokenized as a string: " << CEscape(text); return; } - output->reserve(output->size() + text.size()); + // Reserve room for new string. The branch is necessary because if + // there is already space available the reserve() call might + // downsize the output. + const size_t new_len = text_size + output->size(); + if (new_len > output->capacity()) { + output->reserve(new_len); + } // Loop through the string copying characters to "output" and // interpreting escape sequences. Note that any invalid escape @@ -671,19 +1079,47 @@ void Tokenizer::ParseStringAppend(const string& text, string* output) { } output->push_back(static_cast(code)); + } else if (*ptr == 'u' || *ptr == 'U') { + uint32 unicode; + const char* end = FetchUnicodePoint(ptr, &unicode); + if (end == ptr) { + // Failure: Just dump out what we saw, don't try to parse it. + output->push_back(*ptr); + } else { + AppendUTF8(unicode, output); + ptr = end - 1; // Because we're about to ++ptr. + } } else { // Some other escape code. output->push_back(TranslateEscape(*ptr)); } - } else if (*ptr == text[0]) { - // Ignore quote matching the starting quote. + } else if (*ptr == text[0] && ptr[1] == '\0') { + // Ignore final quote matching the starting quote. } else { output->push_back(*ptr); } } +} - return; +template +static bool AllInClass(const string& s) { + for (int i = 0; i < s.size(); ++i) { + if (!CharacterClass::InClass(s[i])) + return false; + } + return true; +} + +bool Tokenizer::IsIdentifier(const string& text) { + // Mirrors IDENTIFIER definition in Tokenizer::Next() above. + if (text.size() == 0) + return false; + if (!Letter::InClass(text.at(0))) + return false; + if (!AllInClass(text.substr(1))) + return false; + return true; } } // namespace io diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h index d115161..2f07116 100644 --- a/src/google/protobuf/io/tokenizer.h +++ b/src/google/protobuf/io/tokenizer.h @@ -38,6 +38,7 @@ #define GOOGLE_PROTOBUF_IO_TOKENIZER_H__ #include +#include #include namespace google { @@ -66,7 +67,8 @@ class LIBPROTOBUF_EXPORT ErrorCollector { // Indicates that there was a warning in the input at the given line and // column numbers. The numbers are zero-based, so you may want to add // 1 to each before printing them. - virtual void AddWarning(int line, int column, const string& message) { } + virtual void AddWarning(int /* line */, int /* column */, + const string& /* message */) { } private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector); @@ -122,16 +124,68 @@ class LIBPROTOBUF_EXPORT Tokenizer { // the token within the input stream. They are zero-based. int line; int column; + int end_column; }; // Get the current token. This is updated when Next() is called. Before // the first call to Next(), current() has type TYPE_START and no contents. const Token& current(); + // Return the previous token -- i.e. what current() returned before the + // previous call to Next(). + const Token& previous(); + // Advance to the next token. Returns false if the end of the input is // reached. bool Next(); + // Like Next(), but also collects comments which appear between the previous + // and next tokens. + // + // Comments which appear to be attached to the previous token are stored + // in *prev_tailing_comments. Comments which appear to be attached to the + // next token are stored in *next_leading_comments. Comments appearing in + // between which do not appear to be attached to either will be added to + // detached_comments. Any of these parameters can be NULL to simply discard + // the comments. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // Only the comment content is returned; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk will + // be stripped from the beginning of each line other than the first. Newlines + // are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // // Detached comment. This is not attached to qux or corge + // // because there are blank lines separating it from both. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + bool NextWithComments(string* prev_trailing_comments, + vector* detached_comments, + string* next_leading_comments); + // Parse helpers --------------------------------------------------- // Parses a TYPE_FLOAT token. This never fails, so long as the text actually @@ -175,11 +229,27 @@ class LIBPROTOBUF_EXPORT Tokenizer { // Sets the comment style. void set_comment_style(CommentStyle style) { comment_style_ = style; } + // Whether to require whitespace between a number and a field name. + // Default is true. Do not use this; for Google-internal cleanup only. + void set_require_space_after_number(bool require) { + require_space_after_number_ = require; + } + + // Whether to allow string literals to span multiple lines. Default is false. + // Do not use this; for Google-internal cleanup only. + void set_allow_multiline_strings(bool allow) { + allow_multiline_strings_ = allow; + } + + // External helper: validate an identifier. + static bool IsIdentifier(const string& text); + // ----------------------------------------------------------------- private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer); Token current_; // Returned by current(). + Token previous_; // Returned by previous(). ZeroCopyInputStream* input_; ErrorCollector* error_collector_; @@ -194,15 +264,18 @@ class LIBPROTOBUF_EXPORT Tokenizer { int line_; int column_; - // Position in buffer_ where StartToken() was called. If the token - // started in the previous buffer, this is zero, and current_.text already - // contains the part of the token from the previous buffer. If not - // currently parsing a token, this is -1. - int token_start_; + // String to which text should be appended as we advance through it. + // Call RecordTo(&str) to start recording and StopRecording() to stop. + // E.g. StartToken() calls RecordTo(¤t_.text). record_start_ is the + // position within the current buffer where recording started. + string* record_target_; + int record_start_; // Options. bool allow_f_after_float_; CommentStyle comment_style_; + bool require_space_after_number_; + bool allow_multiline_strings_; // Since we count columns we need to interpret tabs somehow. We'll take // the standard 8-character definition for lack of any way to do better. @@ -217,6 +290,9 @@ class LIBPROTOBUF_EXPORT Tokenizer { // Read a new buffer from the input. void Refresh(); + inline void RecordTo(string* target); + inline void StopRecording(); + // Called when the current character is the first character of a new // token (not including whitespace or comments). inline void StartToken(); @@ -249,9 +325,28 @@ class LIBPROTOBUF_EXPORT Tokenizer { TokenType ConsumeNumber(bool started_with_zero, bool started_with_dot); // Consume the rest of a line. - void ConsumeLineComment(); + void ConsumeLineComment(string* content); // Consume until "*/". - void ConsumeBlockComment(); + void ConsumeBlockComment(string* content); + + enum NextCommentStatus { + // Started a line comment. + LINE_COMMENT, + + // Started a block comment. + BLOCK_COMMENT, + + // Consumed a slash, then realized it wasn't a comment. current_ has + // been filled in with a slash token. The caller should return it. + SLASH_NOT_COMMENT, + + // We do not appear to be starting a comment here. + NO_COMMENT + }; + + // If we're at the start of a new comment, consume it and return what kind + // of comment it is. + NextCommentStatus TryConsumeCommentStart(); // ----------------------------------------------------------------- // These helper methods make the parsing code more readable. The @@ -291,6 +386,10 @@ inline const Tokenizer::Token& Tokenizer::current() { return current_; } +inline const Tokenizer::Token& Tokenizer::previous() { + return previous_; +} + inline void Tokenizer::ParseString(const string& text, string* output) { output->clear(); ParseStringAppend(text, output); diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc index 358ec56..b39279b 100644 --- a/src/google/protobuf/io/tokenizer_unittest.cc +++ b/src/google/protobuf/io/tokenizer_unittest.cc @@ -32,9 +32,10 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include -#include #include +#include + +#include #include #include @@ -257,6 +258,7 @@ TEST_2D(TokenizerTest, SimpleTokens, kSimpleTokenCases, kBlockSizes) { EXPECT_EQ("", tokenizer.current().text); EXPECT_EQ(0, tokenizer.current().line); EXPECT_EQ(0, tokenizer.current().column); + EXPECT_EQ(0, tokenizer.current().end_column); // Parse the token. ASSERT_TRUE(tokenizer.Next()); @@ -268,6 +270,8 @@ TEST_2D(TokenizerTest, SimpleTokens, kSimpleTokenCases, kBlockSizes) { // Check that it is located at the beginning of the input EXPECT_EQ(0, tokenizer.current().line); EXPECT_EQ(0, tokenizer.current().column); + EXPECT_EQ(kSimpleTokenCases_case.input.size(), + tokenizer.current().end_column); // There should be no more input. EXPECT_FALSE(tokenizer.Next()); @@ -277,6 +281,8 @@ TEST_2D(TokenizerTest, SimpleTokens, kSimpleTokenCases, kBlockSizes) { EXPECT_EQ("", tokenizer.current().text); EXPECT_EQ(0, tokenizer.current().line); EXPECT_EQ(kSimpleTokenCases_case.input.size(), tokenizer.current().column); + EXPECT_EQ(kSimpleTokenCases_case.input.size(), + tokenizer.current().end_column); // There should be no errors. EXPECT_TRUE(error_collector.text_.empty()); @@ -339,76 +345,77 @@ MultiTokenCase kMultiTokenCases[] = { // Test all token types at the same time. { "foo 1 1.2 + 'bar'", { - { Tokenizer::TYPE_IDENTIFIER, "foo" , 0, 0 }, - { Tokenizer::TYPE_INTEGER , "1" , 0, 4 }, - { Tokenizer::TYPE_FLOAT , "1.2" , 0, 6 }, - { Tokenizer::TYPE_SYMBOL , "+" , 0, 10 }, - { Tokenizer::TYPE_STRING , "'bar'", 0, 12 }, - { Tokenizer::TYPE_END , "" , 0, 17 }, + { Tokenizer::TYPE_IDENTIFIER, "foo" , 0, 0, 3 }, + { Tokenizer::TYPE_INTEGER , "1" , 0, 4, 5 }, + { Tokenizer::TYPE_FLOAT , "1.2" , 0, 6, 9 }, + { Tokenizer::TYPE_SYMBOL , "+" , 0, 10, 11 }, + { Tokenizer::TYPE_STRING , "'bar'", 0, 12, 17 }, + { Tokenizer::TYPE_END , "" , 0, 17, 17 }, }}, // Test that consecutive symbols are parsed as separate tokens. { "!@+%", { - { Tokenizer::TYPE_SYMBOL , "!" , 0, 0 }, - { Tokenizer::TYPE_SYMBOL , "@" , 0, 1 }, - { Tokenizer::TYPE_SYMBOL , "+" , 0, 2 }, - { Tokenizer::TYPE_SYMBOL , "%" , 0, 3 }, - { Tokenizer::TYPE_END , "" , 0, 4 }, + { Tokenizer::TYPE_SYMBOL , "!" , 0, 0, 1 }, + { Tokenizer::TYPE_SYMBOL , "@" , 0, 1, 2 }, + { Tokenizer::TYPE_SYMBOL , "+" , 0, 2, 3 }, + { Tokenizer::TYPE_SYMBOL , "%" , 0, 3, 4 }, + { Tokenizer::TYPE_END , "" , 0, 4, 4 }, }}, // Test that newlines affect line numbers correctly. { "foo bar\nrab oof", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 4 }, - { Tokenizer::TYPE_IDENTIFIER, "rab", 1, 0 }, - { Tokenizer::TYPE_IDENTIFIER, "oof", 1, 4 }, - { Tokenizer::TYPE_END , "" , 1, 7 }, + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 4, 7 }, + { Tokenizer::TYPE_IDENTIFIER, "rab", 1, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "oof", 1, 4, 7 }, + { Tokenizer::TYPE_END , "" , 1, 7, 7 }, }}, // Test that tabs affect column numbers correctly. { "foo\tbar \tbaz", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 8 }, - { Tokenizer::TYPE_IDENTIFIER, "baz", 0, 16 }, - { Tokenizer::TYPE_END , "" , 0, 19 }, + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 8, 11 }, + { Tokenizer::TYPE_IDENTIFIER, "baz", 0, 16, 19 }, + { Tokenizer::TYPE_END , "" , 0, 19, 19 }, + }}, + + // Test that tabs in string literals affect column numbers correctly. + { "\"foo\tbar\" baz", { + { Tokenizer::TYPE_STRING , "\"foo\tbar\"", 0, 0, 12 }, + { Tokenizer::TYPE_IDENTIFIER, "baz" , 0, 13, 16 }, + { Tokenizer::TYPE_END , "" , 0, 16, 16 }, }}, // Test that line comments are ignored. { "foo // This is a comment\n" "bar // This is another comment", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 0 }, - { Tokenizer::TYPE_END , "" , 1, 30 }, + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 0, 3 }, + { Tokenizer::TYPE_END , "" , 1, 30, 30 }, }}, // Test that block comments are ignored. { "foo /* This is a block comment */ bar", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 34 }, - { Tokenizer::TYPE_END , "" , 0, 37 }, + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 34, 37 }, + { Tokenizer::TYPE_END , "" , 0, 37, 37 }, }}, // Test that sh-style comments are not ignored by default. { "foo # bar\n" "baz", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0 }, - { Tokenizer::TYPE_SYMBOL , "#" , 0, 4 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 6 }, - { Tokenizer::TYPE_IDENTIFIER, "baz", 1, 0 }, - { Tokenizer::TYPE_END , "" , 1, 3 }, - }}, - - // Bytes with the high-order bit set should not be seen as control characters. - { "\300", { - { Tokenizer::TYPE_SYMBOL, "\300", 0, 0 }, - { Tokenizer::TYPE_END , "" , 0, 1 }, + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_SYMBOL , "#" , 0, 4, 5 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 6, 9 }, + { Tokenizer::TYPE_IDENTIFIER, "baz", 1, 0, 3 }, + { Tokenizer::TYPE_END , "" , 1, 3, 3 }, }}, // Test all whitespace chars { "foo\n\t\r\v\fbar", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 11 }, - { Tokenizer::TYPE_END , "" , 1, 14 }, + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 11, 14 }, + { Tokenizer::TYPE_END , "" , 1, 14, 14 }, }}, }; @@ -425,6 +432,7 @@ TEST_2D(TokenizerTest, MultipleTokens, kMultiTokenCases, kBlockSizes) { EXPECT_EQ("", tokenizer.current().text); EXPECT_EQ(0, tokenizer.current().line); EXPECT_EQ(0, tokenizer.current().column); + EXPECT_EQ(0, tokenizer.current().end_column); // Loop through all expected tokens. int i = 0; @@ -434,6 +442,8 @@ TEST_2D(TokenizerTest, MultipleTokens, kMultiTokenCases, kBlockSizes) { SCOPED_TRACE(testing::Message() << "Token #" << i << ": " << token.text); + Tokenizer::Token previous = tokenizer.current(); + // Next() should only return false when it hits the end token. if (token.type != Tokenizer::TYPE_END) { ASSERT_TRUE(tokenizer.Next()); @@ -441,11 +451,19 @@ TEST_2D(TokenizerTest, MultipleTokens, kMultiTokenCases, kBlockSizes) { ASSERT_FALSE(tokenizer.Next()); } + // Check that the previous token is set correctly. + EXPECT_EQ(previous.type, tokenizer.previous().type); + EXPECT_EQ(previous.text, tokenizer.previous().text); + EXPECT_EQ(previous.line, tokenizer.previous().line); + EXPECT_EQ(previous.column, tokenizer.previous().column); + EXPECT_EQ(previous.end_column, tokenizer.previous().end_column); + // Check that the token matches the expected one. EXPECT_EQ(token.type, tokenizer.current().type); EXPECT_EQ(token.text, tokenizer.current().text); EXPECT_EQ(token.line, tokenizer.current().line); EXPECT_EQ(token.column, tokenizer.current().column); + EXPECT_EQ(token.end_column, tokenizer.current().end_column); } while (token.type != Tokenizer::TYPE_END); @@ -491,6 +509,217 @@ TEST_1D(TokenizerTest, ShCommentStyle, kBlockSizes) { // ------------------------------------------------------------------- +// In each case, the input is expected to have two tokens named "prev" and +// "next" with comments in between. +struct DocCommentCase { + string input; + + const char* prev_trailing_comments; + const char* detached_comments[10]; + const char* next_leading_comments; +}; + +inline ostream& operator<<(ostream& out, + const DocCommentCase& test_case) { + return out << CEscape(test_case.input); +} + +DocCommentCase kDocCommentCases[] = { + { + "prev next", + + "", + {}, + "" + }, + + { + "prev /* ignored */ next", + + "", + {}, + "" + }, + + { + "prev // trailing comment\n" + "next", + + " trailing comment\n", + {}, + "" + }, + + { + "prev\n" + "// leading comment\n" + "// line 2\n" + "next", + + "", + {}, + " leading comment\n" + " line 2\n" + }, + + { + "prev\n" + "// trailing comment\n" + "// line 2\n" + "\n" + "next", + + " trailing comment\n" + " line 2\n", + {}, + "" + }, + + { + "prev // trailing comment\n" + "// leading comment\n" + "// line 2\n" + "next", + + " trailing comment\n", + {}, + " leading comment\n" + " line 2\n" + }, + + { + "prev /* trailing block comment */\n" + "/* leading block comment\n" + " * line 2\n" + " * line 3 */" + "next", + + " trailing block comment ", + {}, + " leading block comment\n" + " line 2\n" + " line 3 " + }, + + { + "prev\n" + "/* trailing block comment\n" + " * line 2\n" + " * line 3\n" + " */\n" + "/* leading block comment\n" + " * line 2\n" + " * line 3 */" + "next", + + " trailing block comment\n" + " line 2\n" + " line 3\n", + {}, + " leading block comment\n" + " line 2\n" + " line 3 " + }, + + { + "prev\n" + "// trailing comment\n" + "\n" + "// detached comment\n" + "// line 2\n" + "\n" + "// second detached comment\n" + "/* third detached comment\n" + " * line 2 */\n" + "// leading comment\n" + "next", + + " trailing comment\n", + { + " detached comment\n" + " line 2\n", + " second detached comment\n", + " third detached comment\n" + " line 2 " + }, + " leading comment\n" + }, + + { + "prev /**/\n" + "\n" + "// detached comment\n" + "\n" + "// leading comment\n" + "next", + + "", + { + " detached comment\n" + }, + " leading comment\n" + }, + + { + "prev /**/\n" + "// leading comment\n" + "next", + + "", + {}, + " leading comment\n" + }, + }; + +TEST_2D(TokenizerTest, DocComments, kDocCommentCases, kBlockSizes) { + // Set up the tokenizer. + TestInputStream input(kDocCommentCases_case.input.data(), + kDocCommentCases_case.input.size(), + kBlockSizes_case); + TestErrorCollector error_collector; + Tokenizer tokenizer(&input, &error_collector); + + // Set up a second tokenizer where we'll pass all NULLs to NextWithComments(). + TestInputStream input2(kDocCommentCases_case.input.data(), + kDocCommentCases_case.input.size(), + kBlockSizes_case); + Tokenizer tokenizer2(&input2, &error_collector); + + tokenizer.Next(); + tokenizer2.Next(); + + EXPECT_EQ("prev", tokenizer.current().text); + EXPECT_EQ("prev", tokenizer2.current().text); + + string prev_trailing_comments; + vector detached_comments; + string next_leading_comments; + tokenizer.NextWithComments(&prev_trailing_comments, &detached_comments, + &next_leading_comments); + tokenizer2.NextWithComments(NULL, NULL, NULL); + EXPECT_EQ("next", tokenizer.current().text); + EXPECT_EQ("next", tokenizer2.current().text); + + EXPECT_EQ(kDocCommentCases_case.prev_trailing_comments, + prev_trailing_comments); + + for (int i = 0; i < detached_comments.size(); i++) { + ASSERT_LT(i, GOOGLE_ARRAYSIZE(kDocCommentCases)); + ASSERT_TRUE(kDocCommentCases_case.detached_comments[i] != NULL); + EXPECT_EQ(kDocCommentCases_case.detached_comments[i], + detached_comments[i]); + } + + // Verify that we matched all the detached comments. + EXPECT_EQ(NULL, + kDocCommentCases_case.detached_comments[detached_comments.size()]); + + EXPECT_EQ(kDocCommentCases_case.next_leading_comments, + next_leading_comments); +} + +// ------------------------------------------------------------------- + // Test parse helpers. It's not really worth setting up a full data-driven // test here. TEST_F(TokenizerTest, ParseInteger) { @@ -506,7 +735,7 @@ TEST_F(TokenizerTest, ParseInteger) { EXPECT_EQ(0, ParseInteger("0x")); uint64 i; -#ifdef GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet +#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet // Test invalid integers that will never be tokenized as integers. EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("zxy", kuint64max, &i), "passed text that could not have been tokenized as an integer"); @@ -518,7 +747,7 @@ TEST_F(TokenizerTest, ParseInteger) { "passed text that could not have been tokenized as an integer"); EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("-1", kuint64max, &i), "passed text that could not have been tokenized as an integer"); -#endif // GTEST_HAS_DEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST // Test overflows. EXPECT_TRUE (Tokenizer::ParseInteger("0", 0, &i)); @@ -561,7 +790,7 @@ TEST_F(TokenizerTest, ParseFloat) { EXPECT_EQ( 0.0, Tokenizer::ParseFloat("1e-9999999999999999999999999999")); EXPECT_EQ(HUGE_VAL, Tokenizer::ParseFloat("1e+9999999999999999999999999999")); -#ifdef GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet +#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet // Test invalid integers that will never be tokenized as integers. EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("zxy"), "passed text that could not have been tokenized as a float"); @@ -569,7 +798,7 @@ TEST_F(TokenizerTest, ParseFloat) { "passed text that could not have been tokenized as a float"); EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("-1.0"), "passed text that could not have been tokenized as a float"); -#endif // GTEST_HAS_DEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST } TEST_F(TokenizerTest, ParseString) { @@ -591,11 +820,27 @@ TEST_F(TokenizerTest, ParseString) { Tokenizer::ParseString("'\\", &output); EXPECT_EQ("\\", output); + // Experiment with Unicode escapes. Here are one-, two- and three-byte Unicode + // characters. + Tokenizer::ParseString("'\\u0024\\u00a2\\u20ac\\U00024b62XX'", &output); + EXPECT_EQ("$¢€𤭢XX", output); + // Same thing encoded using UTF16. + Tokenizer::ParseString("'\\u0024\\u00a2\\u20ac\\ud852\\udf62XX'", &output); + EXPECT_EQ("$¢€𤭢XX", output); + // Here's some broken UTF16; there's a head surrogate with no tail surrogate. + // We just output this as if it were UTF8; it's not a defined code point, but + // it has a defined encoding. + Tokenizer::ParseString("'\\ud852XX'", &output); + EXPECT_EQ("\xed\xa1\x92XX", output); + // Malformed escape: Demons may fly out of the nose. + Tokenizer::ParseString("\\u0", &output); + EXPECT_EQ("u0", output); + // Test invalid strings that will never be tokenized as strings. -#ifdef GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet +#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet EXPECT_DEBUG_DEATH(Tokenizer::ParseString("", &output), "passed text that could not have been tokenized as a string"); -#endif // GTEST_HAS_DEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST } TEST_F(TokenizerTest, ParseStringAppend) { @@ -632,9 +877,15 @@ ErrorCase kErrorCases[] = { { "'\\x' foo", true, "0:3: Expected hex digits for escape sequence.\n" }, { "'foo", false, - "0:4: String literals cannot cross line boundaries.\n" }, + "0:4: Unexpected end of string.\n" }, { "'bar\nfoo", true, "0:4: String literals cannot cross line boundaries.\n" }, + { "'\\u01' foo", true, + "0:5: Expected four hex digits for \\u escape sequence.\n" }, + { "'\\u01' foo", true, + "0:5: Expected four hex digits for \\u escape sequence.\n" }, + { "'\\uXYZ' foo", true, + "0:3: Expected four hex digits for \\u escape sequence.\n" }, // Integer errors. { "123foo", true, @@ -694,6 +945,10 @@ ErrorCase kErrorCases[] = { "0:0: Invalid control characters encountered in text.\n" }, { string("\0\0foo", 5), true, "0:0: Invalid control characters encountered in text.\n" }, + + // Check error from high order bits set + { "\300foo", true, + "0:0: Interpreting non ascii codepoint 192.\n" }, }; TEST_2D(TokenizerTest, Errors, kErrorCases, kBlockSizes) { @@ -711,7 +966,7 @@ TEST_2D(TokenizerTest, Errors, kErrorCases, kBlockSizes) { } // Check that the errors match what was expected. - EXPECT_EQ(error_collector.text_, kErrorCases_case.errors); + EXPECT_EQ(kErrorCases_case.errors, error_collector.text_); // If the error was recoverable, make sure we saw "foo" after it. if (kErrorCases_case.recoverable) { @@ -737,6 +992,7 @@ TEST_1D(TokenizerTest, BackUpOnDestruction, kBlockSizes) { EXPECT_EQ(strlen("foo"), input.ByteCount()); } + } // namespace } // namespace io } // namespace protobuf diff --git a/src/google/protobuf/io/zero_copy_stream.cc b/src/google/protobuf/io/zero_copy_stream.cc index dad6ff1..4d53f29 100644 --- a/src/google/protobuf/io/zero_copy_stream.cc +++ b/src/google/protobuf/io/zero_copy_stream.cc @@ -34,6 +34,7 @@ #include +#include namespace google { namespace protobuf { @@ -43,6 +44,14 @@ ZeroCopyInputStream::~ZeroCopyInputStream() {} ZeroCopyOutputStream::~ZeroCopyOutputStream() {} +bool ZeroCopyOutputStream::WriteAliasedRaw(const void* /* data */, + int /* size */) { + GOOGLE_LOG(FATAL) << "This ZeroCopyOutputStream doesn't support aliasing. " + "Reaching here usually means a ZeroCopyOutputStream " + "implementation bug."; + return false; +} + } // namespace io } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/io/zero_copy_stream.h b/src/google/protobuf/io/zero_copy_stream.h index db5326f..f892122 100644 --- a/src/google/protobuf/io/zero_copy_stream.h +++ b/src/google/protobuf/io/zero_copy_stream.h @@ -226,6 +226,16 @@ class LIBPROTOBUF_EXPORT ZeroCopyOutputStream { // Returns the total number of bytes written since this object was created. virtual int64 ByteCount() const = 0; + // Write a given chunk of data to the output. Some output streams may + // implement this in a way that avoids copying. Check AllowsAliasing() before + // calling WriteAliasedRaw(). It will GOOGLE_CHECK fail if WriteAliasedRaw() is + // called on a stream that does not allow aliasing. + // + // NOTE: It is caller's responsibility to ensure that the chunk of memory + // remains live until all of the data has been consumed from the stream. + virtual bool WriteAliasedRaw(const void* data, int size); + virtual bool AllowsAliasing() const { return false; } + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream); diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc index 1384c74..7829a29 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl.cc @@ -46,7 +46,8 @@ #include #include -#include +#include + namespace google { namespace protobuf { @@ -412,7 +413,9 @@ int64 ConcatenatingInputStream::ByteCount() const { LimitingInputStream::LimitingInputStream(ZeroCopyInputStream* input, int64 limit) - : input_(input), limit_(limit) {} + : input_(input), limit_(limit) { + prior_bytes_read_ = input_->ByteCount(); +} LimitingInputStream::~LimitingInputStream() { // If we overshot the limit, back up. @@ -456,9 +459,9 @@ bool LimitingInputStream::Skip(int count) { int64 LimitingInputStream::ByteCount() const { if (limit_ < 0) { - return input_->ByteCount() + limit_; + return input_->ByteCount() + limit_ - prior_bytes_read_; } else { - return input_->ByteCount(); + return input_->ByteCount() - prior_bytes_read_; } } diff --git a/src/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h index 9fedb00..8382709 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.h +++ b/src/google/protobuf/io/zero_copy_stream_impl.h @@ -344,6 +344,7 @@ class LIBPROTOBUF_EXPORT LimitingInputStream : public ZeroCopyInputStream { private: ZeroCopyInputStream* input_; int64 limit_; // Decreases as we go, becomes negative if we overshoot. + int64 prior_bytes_read_; // Bytes read on underlying stream at construction GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream); }; diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc index e801251..d186a98 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc @@ -32,9 +32,13 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include +#include + +#include +#include + #include -#include +#include namespace google { namespace protobuf { @@ -159,15 +163,23 @@ bool StringOutputStream::Next(void** data, int* size) { // without a memory allocation this way. STLStringResizeUninitialized(target_, target_->capacity()); } else { - // Size has reached capacity, so double the size. Also make sure - // that the new size is at least kMinimumSize. + // Size has reached capacity, try to double the size. + if (old_size > std::numeric_limits::max() / 2) { + // Can not double the size otherwise it is going to cause integer + // overflow in the expression below: old_size * 2 "; + GOOGLE_LOG(ERROR) << "Cannot allocate buffer larger than kint32max for " + << "StringOutputStream."; + return false; + } + // Double the size, also make sure that the new size is at least + // kMinimumSize. STLStringResizeUninitialized( target_, max(old_size * 2, kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness. } - *data = string_as_array(target_) + old_size; + *data = mutable_string_data(target_) + old_size; *size = target_->size() - old_size; return true; } diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h index 153f543..b980143 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -48,6 +48,7 @@ #include #include #include +#include namespace google { @@ -333,6 +334,19 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea // =================================================================== +// Return a pointer to mutable characters underlying the given string. The +// return value is valid until the next time the string is resized. We +// trust the caller to treat the return value as an array of length s->size(). +inline char* mutable_string_data(string* s) { +#ifdef LANG_CXX11 + // This should be simpler & faster than string_as_array() because the latter + // is guaranteed to return NULL when *s is empty, so it has to check for that. + return &(*s)[0]; +#else + return string_as_array(s); +#endif +} + } // namespace io } // namespace protobuf diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc index 8229ee6..75eb2a4 100644 --- a/src/google/protobuf/io/zero_copy_stream_unittest.cc +++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc @@ -61,6 +61,7 @@ #include #include +#include #if HAVE_ZLIB #include @@ -285,6 +286,57 @@ TEST_F(IoTest, ArrayIo) { } } +TEST_F(IoTest, TwoSessionWrite) { + // Test that two concatenated write sessions read correctly + + static const char* strA = "0123456789"; + static const char* strB = "WhirledPeas"; + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + char* temp_buffer = new char[40]; + + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + ArrayOutputStream* output = + new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]); + CodedOutputStream* coded_output = new CodedOutputStream(output); + coded_output->WriteVarint32(strlen(strA)); + coded_output->WriteRaw(strA, strlen(strA)); + delete coded_output; // flush + int64 pos = output->ByteCount(); + delete output; + output = new ArrayOutputStream( + buffer + pos, kBufferSize - pos, kBlockSizes[i]); + coded_output = new CodedOutputStream(output); + coded_output->WriteVarint32(strlen(strB)); + coded_output->WriteRaw(strB, strlen(strB)); + delete coded_output; // flush + int64 size = pos + output->ByteCount(); + delete output; + + ArrayInputStream* input = + new ArrayInputStream(buffer, size, kBlockSizes[j]); + CodedInputStream* coded_input = new CodedInputStream(input); + uint32 insize; + EXPECT_TRUE(coded_input->ReadVarint32(&insize)); + EXPECT_EQ(strlen(strA), insize); + EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); + EXPECT_EQ(0, memcmp(temp_buffer, strA, insize)); + + EXPECT_TRUE(coded_input->ReadVarint32(&insize)); + EXPECT_EQ(strlen(strB), insize); + EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); + EXPECT_EQ(0, memcmp(temp_buffer, strB, insize)); + + delete coded_input; + delete input; + } + } + + delete [] temp_buffer; + delete [] buffer; +} + #if HAVE_ZLIB TEST_F(IoTest, GzipIo) { const int kBufferSize = 2*1024; @@ -296,9 +348,49 @@ TEST_F(IoTest, GzipIo) { int size; { ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]); - GzipOutputStream gzout( - &output, GzipOutputStream::GZIP, gzip_buffer_size); + GzipOutputStream::Options options; + options.format = GzipOutputStream::GZIP; + if (gzip_buffer_size != -1) { + options.buffer_size = gzip_buffer_size; + } + GzipOutputStream gzout(&output, options); + WriteStuff(&gzout); + gzout.Close(); + size = output.ByteCount(); + } + { + ArrayInputStream input(buffer, size, kBlockSizes[j]); + GzipInputStream gzin( + &input, GzipInputStream::GZIP, gzip_buffer_size); + ReadStuff(&gzin); + } + } + } + } + delete [] buffer; +} + +TEST_F(IoTest, GzipIoWithFlush) { + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + // We start with i = 4 as we want a block size > 6. With block size <= 6 + // Flush() fills up the entire 2K buffer with flush markers and the test + // fails. See documentation for Flush() for more detail. + for (int i = 4; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + for (int z = 0; z < kBlockSizeCount; z++) { + int gzip_buffer_size = kBlockSizes[z]; + int size; + { + ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]); + GzipOutputStream::Options options; + options.format = GzipOutputStream::GZIP; + if (gzip_buffer_size != -1) { + options.buffer_size = gzip_buffer_size; + } + GzipOutputStream gzout(&output, options); WriteStuff(&gzout); + EXPECT_TRUE(gzout.Flush()); gzout.Close(); size = output.ByteCount(); } @@ -314,6 +406,64 @@ TEST_F(IoTest, GzipIo) { delete [] buffer; } +TEST_F(IoTest, GzipIoContiguousFlushes) { + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + + int block_size = kBlockSizes[4]; + int gzip_buffer_size = block_size; + int size; + + ArrayOutputStream output(buffer, kBufferSize, block_size); + GzipOutputStream::Options options; + options.format = GzipOutputStream::GZIP; + if (gzip_buffer_size != -1) { + options.buffer_size = gzip_buffer_size; + } + GzipOutputStream gzout(&output, options); + WriteStuff(&gzout); + EXPECT_TRUE(gzout.Flush()); + EXPECT_TRUE(gzout.Flush()); + gzout.Close(); + size = output.ByteCount(); + + ArrayInputStream input(buffer, size, block_size); + GzipInputStream gzin( + &input, GzipInputStream::GZIP, gzip_buffer_size); + ReadStuff(&gzin); + + delete [] buffer; +} + +TEST_F(IoTest, GzipIoReadAfterFlush) { + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + + int block_size = kBlockSizes[4]; + int gzip_buffer_size = block_size; + int size; + ArrayOutputStream output(buffer, kBufferSize, block_size); + GzipOutputStream::Options options; + options.format = GzipOutputStream::GZIP; + if (gzip_buffer_size != -1) { + options.buffer_size = gzip_buffer_size; + } + + GzipOutputStream gzout(&output, options); + WriteStuff(&gzout); + EXPECT_TRUE(gzout.Flush()); + size = output.ByteCount(); + + ArrayInputStream input(buffer, size, block_size); + GzipInputStream gzin( + &input, GzipInputStream::GZIP, gzip_buffer_size); + ReadStuff(&gzin); + + gzout.Close(); + + delete [] buffer; +} + TEST_F(IoTest, ZlibIo) { const int kBufferSize = 2*1024; uint8* buffer = new uint8[kBufferSize]; @@ -324,8 +474,12 @@ TEST_F(IoTest, ZlibIo) { int size; { ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]); - GzipOutputStream gzout( - &output, GzipOutputStream::ZLIB, gzip_buffer_size); + GzipOutputStream::Options options; + options.format = GzipOutputStream::ZLIB; + if (gzip_buffer_size != -1) { + options.buffer_size = gzip_buffer_size; + } + GzipOutputStream gzout(&output, options); WriteStuff(&gzout); gzout.Close(); size = output.ByteCount(); @@ -348,7 +502,9 @@ TEST_F(IoTest, ZlibIoInputAutodetect) { int size; { ArrayOutputStream output(buffer, kBufferSize); - GzipOutputStream gzout(&output, GzipOutputStream::ZLIB); + GzipOutputStream::Options options; + options.format = GzipOutputStream::ZLIB; + GzipOutputStream gzout(&output, options); WriteStuff(&gzout); gzout.Close(); size = output.ByteCount(); @@ -360,7 +516,9 @@ TEST_F(IoTest, ZlibIoInputAutodetect) { } { ArrayOutputStream output(buffer, kBufferSize); - GzipOutputStream gzout(&output, GzipOutputStream::GZIP); + GzipOutputStream::Options options; + options.format = GzipOutputStream::GZIP; + GzipOutputStream gzout(&output, options); WriteStuff(&gzout); gzout.Close(); size = output.ByteCount(); @@ -402,9 +560,10 @@ TEST_F(IoTest, CompressionOptions) { // Some ad-hoc testing of compression options. string golden; - File::ReadFileToStringOrDie( - TestSourceDir() + "/google/protobuf/testdata/golden_message", - &golden); + GOOGLE_CHECK_OK(File::GetContents( + TestSourceDir() + + "/google/protobuf/testdata/golden_message", + &golden, true)); GzipOutputStream::Options options; string gzip_compressed = Compress(golden, options); @@ -432,6 +591,71 @@ TEST_F(IoTest, CompressionOptions) { EXPECT_TRUE(Uncompress(gzip_compressed) == golden); EXPECT_TRUE(Uncompress(zlib_compressed) == golden); } + +TEST_F(IoTest, TwoSessionWriteGzip) { + // Test that two concatenated gzip streams can be read correctly + + static const char* strA = "0123456789"; + static const char* strB = "QuickBrownFox"; + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + char* temp_buffer = new char[40]; + + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + ArrayOutputStream* output = + new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]); + GzipOutputStream* gzout = new GzipOutputStream(output); + CodedOutputStream* coded_output = new CodedOutputStream(gzout); + int32 outlen = strlen(strA) + 1; + coded_output->WriteVarint32(outlen); + coded_output->WriteRaw(strA, outlen); + delete coded_output; // flush + delete gzout; // flush + int64 pos = output->ByteCount(); + delete output; + output = new ArrayOutputStream( + buffer + pos, kBufferSize - pos, kBlockSizes[i]); + gzout = new GzipOutputStream(output); + coded_output = new CodedOutputStream(gzout); + outlen = strlen(strB) + 1; + coded_output->WriteVarint32(outlen); + coded_output->WriteRaw(strB, outlen); + delete coded_output; // flush + delete gzout; // flush + int64 size = pos + output->ByteCount(); + delete output; + + ArrayInputStream* input = + new ArrayInputStream(buffer, size, kBlockSizes[j]); + GzipInputStream* gzin = new GzipInputStream(input); + CodedInputStream* coded_input = new CodedInputStream(gzin); + uint32 insize; + EXPECT_TRUE(coded_input->ReadVarint32(&insize)); + EXPECT_EQ(strlen(strA) + 1, insize); + EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); + EXPECT_EQ(0, memcmp(temp_buffer, strA, insize)) + << "strA=" << strA << " in=" << temp_buffer; + + EXPECT_TRUE(coded_input->ReadVarint32(&insize)); + EXPECT_EQ(strlen(strB) + 1, insize); + EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); + EXPECT_EQ(0, memcmp(temp_buffer, strB, insize)) + << " out_block_size=" << kBlockSizes[i] + << " in_block_size=" << kBlockSizes[j] + << " pos=" << pos + << " size=" << size + << " strB=" << strB << " in=" << temp_buffer; + + delete coded_input; + delete gzin; + delete input; + } + } + + delete [] temp_buffer; + delete [] buffer; +} #endif // There is no string input, only string output. Also, it doesn't support @@ -700,6 +924,26 @@ TEST_F(IoTest, LimitingInputStream) { ReadStuff(&input); } +// Checks that ByteCount works correctly for LimitingInputStreams where the +// underlying stream has already been read. +TEST_F(IoTest, LimitingInputStreamByteCount) { + const int kHalfBufferSize = 128; + const int kBufferSize = kHalfBufferSize * 2; + uint8 buffer[kBufferSize]; + + // Set up input. Only allow half to be read at once. + ArrayInputStream array_input(buffer, kBufferSize, kHalfBufferSize); + const void* data; + int size; + EXPECT_TRUE(array_input.Next(&data, &size)); + EXPECT_EQ(kHalfBufferSize, array_input.ByteCount()); + // kHalfBufferSize - 1 to test limiting logic as well. + LimitingInputStream input(&array_input, kHalfBufferSize - 1); + EXPECT_EQ(0, input.ByteCount()); + EXPECT_TRUE(input.Next(&data, &size)); + EXPECT_EQ(kHalfBufferSize - 1 , input.ByteCount()); +} + // Check that a zero-size array doesn't confuse the code. TEST(ZeroSizeArray, Input) { ArrayInputStream input(NULL, 0); diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc index ffeec3c..6f385bd 100644 --- a/src/google/protobuf/lite_unittest.cc +++ b/src/google/protobuf/lite_unittest.cc @@ -33,13 +33,59 @@ #include #include -#include #include +#include +#include +#include +#include +#include +#include using namespace std; +namespace { +// Helper methods to test parsing merge behavior. +void ExpectMessageMerged(const google::protobuf::unittest::TestAllTypesLite& message) { + GOOGLE_CHECK(message.optional_int32() == 3); + GOOGLE_CHECK(message.optional_int64() == 2); + GOOGLE_CHECK(message.optional_string() == "hello"); +} + +void AssignParsingMergeMessages( + google::protobuf::unittest::TestAllTypesLite* msg1, + google::protobuf::unittest::TestAllTypesLite* msg2, + google::protobuf::unittest::TestAllTypesLite* msg3) { + msg1->set_optional_int32(1); + msg2->set_optional_int64(2); + msg3->set_optional_int32(3); + msg3->set_optional_string("hello"); +} + +void SetAllTypesInEmptyMessageUnknownFields( + google::protobuf::unittest::TestEmptyMessageLite* empty_message) { + protobuf_unittest::TestAllTypesLite message; + google::protobuf::TestUtilLite::ExpectClear(message); + google::protobuf::TestUtilLite::SetAllFields(&message); + string data = message.SerializeAsString(); + empty_message->ParseFromString(data); +} + +void SetSomeTypesInEmptyMessageUnknownFields( + google::protobuf::unittest::TestEmptyMessageLite* empty_message) { + protobuf_unittest::TestAllTypesLite message; + google::protobuf::TestUtilLite::ExpectClear(message); + message.set_optional_int32(101); + message.set_optional_int64(102); + message.set_optional_uint32(103); + message.set_optional_uint64(104); + string data = message.SerializeAsString(); + empty_message->ParseFromString(data); +} + +} // namespace + int main(int argc, char* argv[]) { - string data, packed_data; + string data, data2, packed_data; { protobuf_unittest::TestAllTypesLite message, message2, message3; @@ -63,7 +109,6 @@ int main(int argc, char* argv[]) { google::protobuf::TestUtilLite::SetAllExtensions(&message); message2.CopyFrom(message); string extensions_data = message.SerializeAsString(); - GOOGLE_CHECK(extensions_data == data); message3.ParseFromString(extensions_data); google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message); google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2); @@ -107,6 +152,199 @@ int main(int argc, char* argv[]) { google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); } + { + // Test that if an optional or required message/group field appears multiple + // times in the input, they need to be merged. + google::protobuf::unittest::TestParsingMergeLite::RepeatedFieldsGenerator generator; + google::protobuf::unittest::TestAllTypesLite* msg1; + google::protobuf::unittest::TestAllTypesLite* msg2; + google::protobuf::unittest::TestAllTypesLite* msg3; + +#define ASSIGN_REPEATED_FIELD(FIELD) \ + msg1 = generator.add_##FIELD(); \ + msg2 = generator.add_##FIELD(); \ + msg3 = generator.add_##FIELD(); \ + AssignParsingMergeMessages(msg1, msg2, msg3) + + ASSIGN_REPEATED_FIELD(field1); + ASSIGN_REPEATED_FIELD(field2); + ASSIGN_REPEATED_FIELD(field3); + ASSIGN_REPEATED_FIELD(ext1); + ASSIGN_REPEATED_FIELD(ext2); + +#undef ASSIGN_REPEATED_FIELD +#define ASSIGN_REPEATED_GROUP(FIELD) \ + msg1 = generator.add_##FIELD()->mutable_field1(); \ + msg2 = generator.add_##FIELD()->mutable_field1(); \ + msg3 = generator.add_##FIELD()->mutable_field1(); \ + AssignParsingMergeMessages(msg1, msg2, msg3) + + ASSIGN_REPEATED_GROUP(group1); + ASSIGN_REPEATED_GROUP(group2); + +#undef ASSIGN_REPEATED_GROUP + + string buffer; + generator.SerializeToString(&buffer); + google::protobuf::unittest::TestParsingMergeLite parsing_merge; + parsing_merge.ParseFromString(buffer); + + // Required and optional fields should be merged. + ExpectMessageMerged(parsing_merge.required_all_types()); + ExpectMessageMerged(parsing_merge.optional_all_types()); + ExpectMessageMerged( + parsing_merge.optionalgroup().optional_group_all_types()); + ExpectMessageMerged(parsing_merge.GetExtension( + google::protobuf::unittest::TestParsingMergeLite::optional_ext)); + + // Repeated fields should not be merged. + GOOGLE_CHECK(parsing_merge.repeated_all_types_size() == 3); + GOOGLE_CHECK(parsing_merge.repeatedgroup_size() == 3); + GOOGLE_CHECK(parsing_merge.ExtensionSize( + google::protobuf::unittest::TestParsingMergeLite::repeated_ext) == 3); + } + + // Test unknown fields support for lite messages. + { + protobuf_unittest::TestAllTypesLite message, message2; + protobuf_unittest::TestEmptyMessageLite empty_message; + google::protobuf::TestUtilLite::ExpectClear(message); + google::protobuf::TestUtilLite::SetAllFields(&message); + data = message.SerializeAsString(); + empty_message.ParseFromString(data); + data.clear(); + data = empty_message.SerializeAsString(); + message2.ParseFromString(data); + data = message2.SerializeAsString(); + google::protobuf::TestUtilLite::ExpectAllFieldsSet(message2); + message.Clear(); + google::protobuf::TestUtilLite::ExpectClear(message); + } + + { + protobuf_unittest::TestAllExtensionsLite message, message2; + protobuf_unittest::TestEmptyMessageLite empty_message; + google::protobuf::TestUtilLite::ExpectExtensionsClear(message); + google::protobuf::TestUtilLite::SetAllExtensions(&message); + data = message.SerializeAsString(); + empty_message.ParseFromString(data); + data.clear(); + data = empty_message.SerializeAsString(); + message2.ParseFromString(data); + data = message2.SerializeAsString(); + google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2); + message.Clear(); + google::protobuf::TestUtilLite::ExpectExtensionsClear(message); + } + + { + protobuf_unittest::TestPackedTypesLite message, message2; + protobuf_unittest::TestEmptyMessageLite empty_message; + google::protobuf::TestUtilLite::ExpectPackedClear(message); + google::protobuf::TestUtilLite::SetPackedFields(&message); + data = message.SerializeAsString(); + empty_message.ParseFromString(data); + data.clear(); + data = empty_message.SerializeAsString(); + message2.ParseFromString(data); + data = message2.SerializeAsString(); + google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message2); + message.Clear(); + google::protobuf::TestUtilLite::ExpectPackedClear(message); + } + + { + protobuf_unittest::TestPackedExtensionsLite message, message2; + protobuf_unittest::TestEmptyMessageLite empty_message; + google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); + google::protobuf::TestUtilLite::SetPackedExtensions(&message); + data = message.SerializeAsString(); + empty_message.ParseFromString(data); + data.clear(); + data = empty_message.SerializeAsString(); + message2.ParseFromString(data); + data = message2.SerializeAsString(); + google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message2); + message.Clear(); + google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); + } + + { + // Test Unknown fields swap + protobuf_unittest::TestEmptyMessageLite empty_message, empty_message2; + SetAllTypesInEmptyMessageUnknownFields(&empty_message); + SetSomeTypesInEmptyMessageUnknownFields(&empty_message2); + data = empty_message.SerializeAsString(); + data2 = empty_message2.SerializeAsString(); + empty_message.Swap(&empty_message2); + GOOGLE_CHECK_EQ(data, empty_message2.SerializeAsString()); + GOOGLE_CHECK_EQ(data2, empty_message.SerializeAsString()); + } + + { + // Test unknown fields swap with self + protobuf_unittest::TestEmptyMessageLite empty_message; + SetAllTypesInEmptyMessageUnknownFields(&empty_message); + data = empty_message.SerializeAsString(); + empty_message.Swap(&empty_message); + GOOGLE_CHECK_EQ(data, empty_message.SerializeAsString()); + } + + { + // Test MergeFrom with unknown fields + protobuf_unittest::TestAllTypesLite message, message2; + protobuf_unittest::TestEmptyMessageLite empty_message, empty_message2; + message.set_optional_int32(101); + message.add_repeated_int32(201); + message.set_optional_nested_enum(google::protobuf::unittest::TestAllTypesLite::BAZ); + message2.set_optional_int64(102); + message2.add_repeated_int64(202); + message2.set_optional_foreign_enum(google::protobuf::unittest::FOREIGN_LITE_BAZ); + + data = message.SerializeAsString(); + empty_message.ParseFromString(data); + data = message2.SerializeAsString(); + empty_message2.ParseFromString(data); + message.MergeFrom(message2); + empty_message.MergeFrom(empty_message2); + + data = empty_message.SerializeAsString(); + message2.ParseFromString(data); + // We do not compare the serialized output of a normal message and a lite + // message because the order of fields do not match. We convert lite message + // back into normal message, then compare. + GOOGLE_CHECK_EQ(message.SerializeAsString(), message2.SerializeAsString()); + } + + { + // Test unknown enum value + protobuf_unittest::TestAllTypesLite message; + string buffer; + { + google::protobuf::io::StringOutputStream output_stream(&buffer); + google::protobuf::io::CodedOutputStream coded_output(&output_stream); + google::protobuf::internal::WireFormatLite::WriteTag( + protobuf_unittest::TestAllTypesLite::kOptionalNestedEnumFieldNumber, + google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT, &coded_output); + coded_output.WriteVarint32(10); + google::protobuf::internal::WireFormatLite::WriteTag( + protobuf_unittest::TestAllTypesLite::kRepeatedNestedEnumFieldNumber, + google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT, &coded_output); + coded_output.WriteVarint32(20); + } + message.ParseFromString(buffer); + data = message.SerializeAsString(); + GOOGLE_CHECK_EQ(data, buffer); + } + + { + // Test Clear with unknown fields + protobuf_unittest::TestEmptyMessageLite empty_message; + SetAllTypesInEmptyMessageUnknownFields(&empty_message); + empty_message.Clear(); + GOOGLE_CHECK_EQ(0, empty_message.unknown_fields().size()); + } + cout << "PASS" << endl; return 0; } diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index 0409a94..2b9a2cb 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -32,7 +32,7 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include +#include #include #include @@ -44,11 +44,12 @@ #include #include #include +#include #include #include #include -#include -#include +#include +#include namespace google { namespace protobuf { @@ -74,7 +75,7 @@ void Message::CheckTypeAndMergeFrom(const MessageLite& other) { void Message::CopyFrom(const Message& from) { const Descriptor* descriptor = GetDescriptor(); GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) - << ": Tried to copy from a message with a different type." + << ": Tried to copy from a message with a different type. " "to: " << descriptor->full_name() << ", " "from:" << from.GetDescriptor()->full_name(); ReflectionOps::Copy(from, this); @@ -99,7 +100,7 @@ void Message::FindInitializationErrors(vector* errors) const { string Message::InitializationErrorString() const { vector errors; FindInitializationErrors(&errors); - return JoinStrings(errors, ", "); + return Join(errors, ", "); } void Message::CheckInitialized() const { @@ -148,7 +149,7 @@ int Message::ByteSize() const { return size; } -void Message::SetCachedSize(int size) const { +void Message::SetCachedSize(int /* size */) const { GOOGLE_LOG(FATAL) << "Message class \"" << GetDescriptor()->full_name() << "\" implements neither SetCachedSize() nor ByteSize(). " "Must implement one or the other."; @@ -182,9 +183,46 @@ bool Message::SerializePartialToOstream(ostream* output) const { } +// ============================================================================= +// Reflection and associated Template Specializations + Reflection::~Reflection() {} -// =================================================================== +#define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE) \ +template<> \ +const RepeatedField& Reflection::GetRepeatedField( \ + const Message& message, const FieldDescriptor* field) const { \ + return *static_cast* >( \ + MutableRawRepeatedField(const_cast(&message), \ + field, CPPTYPE, CTYPE, NULL)); \ +} \ + \ +template<> \ +RepeatedField* Reflection::MutableRepeatedField( \ + Message* message, const FieldDescriptor* field) const { \ + return static_cast* >( \ + MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \ +} + +HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1); +HANDLE_TYPE(int64, FieldDescriptor::CPPTYPE_INT64, -1); +HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1); +HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1); +HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1); +HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1); +HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1); + + +#undef HANDLE_TYPE + +void* Reflection::MutableRawRepeatedString( + Message* message, const FieldDescriptor* field, bool is_string) const { + return MutableRawRepeatedField(message, field, + FieldDescriptor::CPPTYPE_STRING, FieldOptions::STRING, NULL); +} + + +// ============================================================================= // MessageFactory MessageFactory::~MessageFactory() {} @@ -258,6 +296,7 @@ void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor, } } + const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) { { ReaderMutexLock lock(&mutex_); diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index c0062f9..8bbf405 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -79,18 +79,19 @@ // // Same as the last block, but do it dynamically via the Message // // reflection interface. // Message* foo = new Foo; -// Descriptor* descriptor = foo->GetDescriptor(); +// const Descriptor* descriptor = foo->GetDescriptor(); // // // Get the descriptors for the fields we're interested in and verify // // their types. -// FieldDescriptor* text_field = descriptor->FindFieldByName("text"); +// const FieldDescriptor* text_field = descriptor->FindFieldByName("text"); // assert(text_field != NULL); // assert(text_field->type() == FieldDescriptor::TYPE_STRING); -// assert(text_field->label() == FieldDescriptor::TYPE_OPTIONAL); -// FieldDescriptor* numbers_field = descriptor->FindFieldByName("numbers"); +// assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL); +// const FieldDescriptor* numbers_field = descriptor-> +// FindFieldByName("numbers"); // assert(numbers_field != NULL); // assert(numbers_field->type() == FieldDescriptor::TYPE_INT32); -// assert(numbers_field->label() == FieldDescriptor::TYPE_REPEATED); +// assert(numbers_field->label() == FieldDescriptor::LABEL_REPEATED); // // // Parse the message. // foo->ParseFromString(data); @@ -109,38 +110,17 @@ #ifndef GOOGLE_PROTOBUF_MESSAGE_H__ #define GOOGLE_PROTOBUF_MESSAGE_H__ -#include -#include - -#ifdef __DECCXX -// HP C++'s iosfwd doesn't work. -#include -#else #include -#endif +#include +#include #include #include +#include -#if defined(_WIN32) && defined(GetMessage) -// windows.h defines GetMessage() as a macro. Let's re-define it as an inline -// function. This is necessary because Reflection has a method called -// GetMessage() which we don't want overridden. The inline function should be -// equivalent for C++ users. -inline BOOL GetMessage_Win32( - LPMSG lpMsg, HWND hWnd, - UINT wMsgFilterMin, UINT wMsgFilterMax) { - return GetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); -} -#undef GetMessage -inline BOOL GetMessage( - LPMSG lpMsg, HWND hWnd, - UINT wMsgFilterMin, UINT wMsgFilterMax) { - return GetMessage_Win32(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); -} -#endif +#define GOOGLE_PROTOBUF_HAS_ONEOF namespace google { namespace protobuf { @@ -151,17 +131,20 @@ class Reflection; class MessageFactory; // Defined in other files. -class Descriptor; // descriptor.h -class FieldDescriptor; // descriptor.h -class EnumDescriptor; // descriptor.h -class EnumValueDescriptor; // descriptor.h +class UnknownFieldSet; // unknown_field_set.h namespace io { class ZeroCopyInputStream; // zero_copy_stream.h class ZeroCopyOutputStream; // zero_copy_stream.h class CodedInputStream; // coded_stream.h class CodedOutputStream; // coded_stream.h } -class UnknownFieldSet; // unknown_field_set.h + + +template +class RepeatedField; // repeated_field.h + +template +class RepeatedPtrField; // repeated_field.h // A container to hold message metadata. struct Metadata { @@ -169,12 +152,6 @@ struct Metadata { const Reflection* reflection; }; -// Returns the EnumDescriptor for enum type E, which must be a -// proto-declared enum type. Code generated by the protocol compiler -// will include specializations of this template for each enum type declared. -template -const EnumDescriptor* GetEnumDescriptor(); - // Abstract interface for protocol messages. // // See also MessageLite, which contains most every-day operations. Message @@ -203,9 +180,10 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { virtual void CopyFrom(const Message& from); // Merge the fields from the given message into this message. Singular - // fields will be overwritten, except for embedded messages which will - // be merged. Repeated fields will be concatenated. The given message - // must be of the same type as this message (i.e. the exact same class). + // fields will be overwritten, if specified in from, except for embedded + // messages which will be merged. Repeated fields will be concatenated. + // The given message must be of the same type as this message (i.e. the + // exact same class). virtual void MergeFrom(const Message& from); // Verifies that IsInitialized() returns true. GOOGLE_CHECK-fails otherwise, with @@ -216,7 +194,7 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { // This is much, much slower than IsInitialized() as it is implemented // purely via reflection. Generally, you should not call this unless you // have already determined that an error exists by calling IsInitialized(). - void FindInitializationErrors(vector* errors) const; + void FindInitializationErrors(std::vector* errors) const; // Like FindInitializationErrors, but joins all the strings, delimited by // commas, and returns them. @@ -378,7 +356,6 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { // write fields from a Reflection without paying attention to the type. class LIBPROTOBUF_EXPORT Reflection { public: - // TODO(kenton): Remove parameter. inline Reflection() {} virtual ~Reflection(); @@ -408,7 +385,27 @@ class LIBPROTOBUF_EXPORT Reflection { virtual void ClearField(Message* message, const FieldDescriptor* field) const = 0; - // Remove the last element of a repeated field. + // Check if the oneof is set. Returns ture if any field in oneof + // is set, false otherwise. + // TODO(jieluo) - make it pure virtual after updating all + // the subclasses. + virtual bool HasOneof(const Message& message, + const OneofDescriptor* oneof_descriptor) const { + return false; + } + + virtual void ClearOneof(Message* message, + const OneofDescriptor* oneof_descriptor) const {} + + // Returns the field descriptor if the oneof is set. NULL otherwise. + // TODO(jieluo) - make it pure virtual. + virtual const FieldDescriptor* GetOneofFieldDescriptor( + const Message& message, + const OneofDescriptor* oneof_descriptor) const { + return NULL; + } + + // Removes the last element of a repeated field. // We don't provide a way to remove any element other than the last // because it invites inefficient use, such as O(n^2) filtering loops // that should have been O(n). If you want to remove an element other @@ -417,15 +414,25 @@ class LIBPROTOBUF_EXPORT Reflection { // call RemoveLast(). virtual void RemoveLast(Message* message, const FieldDescriptor* field) const = 0; + // Removes the last element of a repeated message field, and returns the + // pointer to the caller. Caller takes ownership of the returned pointer. + virtual Message* ReleaseLast(Message* message, + const FieldDescriptor* field) const = 0; // Swap the complete contents of two messages. virtual void Swap(Message* message1, Message* message2) const = 0; + // Swap fields listed in fields vector of two messages. + virtual void SwapFields(Message* message1, + Message* message2, + const std::vector& fields) + const = 0; + // Swap two elements of a repeated field. virtual void SwapElements(Message* message, - const FieldDescriptor* field, - int index1, - int index2) const = 0; + const FieldDescriptor* field, + int index1, + int index2) const = 0; // List all fields of the message which are currently set. This includes // extensions. Singular fields will only be listed if HasField(field) would @@ -433,7 +440,7 @@ class LIBPROTOBUF_EXPORT Reflection { // would return non-zero. Fields (both normal fields and extension fields) // will be listed ordered by field number. virtual void ListFields(const Message& message, - vector* output) const = 0; + std::vector* output) const = 0; // Singular field getters ------------------------------------------ // These get the value of a non-repeated field. They return the default @@ -518,6 +525,23 @@ class LIBPROTOBUF_EXPORT Reflection { virtual Message* MutableMessage(Message* message, const FieldDescriptor* field, MessageFactory* factory = NULL) const = 0; + // Replaces the message specified by 'field' with the already-allocated object + // sub_message, passing ownership to the message. If the field contained a + // message, that message is deleted. If sub_message is NULL, the field is + // cleared. + virtual void SetAllocatedMessage(Message* message, + Message* sub_message, + const FieldDescriptor* field) const = 0; + // Releases the message specified by 'field' and returns the pointer, + // ReleaseMessage() will return the message the message object if it exists. + // Otherwise, it may or may not return NULL. In any case, if the return value + // is non-NULL, the caller takes ownership of the pointer. + // If the field existed (HasField() is true), then the returned pointer will + // be the same as the pointer returned by MutableMessage(). + // This function has the same effect as ClearField(). + virtual Message* ReleaseMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory = NULL) const = 0; // Repeated field getters ------------------------------------------ @@ -625,7 +649,39 @@ class LIBPROTOBUF_EXPORT Reflection { MessageFactory* factory = NULL) const = 0; - // Extensions ------------------------------------------------------ + // Repeated field accessors ------------------------------------------------- + // The methods above, e.g. GetRepeatedInt32(msg, fd, index), provide singular + // access to the data in a RepeatedField. The methods below provide aggregate + // access by exposing the RepeatedField object itself with the Message. + // Applying these templates to inappropriate types will lead to an undefined + // reference at link time (e.g. GetRepeatedField<***double>), or possibly a + // template matching error at compile time (e.g. GetRepeatedPtrField). + // + // Usage example: my_doubs = refl->GetRepeatedField(msg, fd); + + // for T = Cord and all protobuf scalar types except enums. + template + const RepeatedField& GetRepeatedField( + const Message&, const FieldDescriptor*) const; + + // for T = Cord and all protobuf scalar types except enums. + template + RepeatedField* MutableRepeatedField( + Message*, const FieldDescriptor*) const; + + // for T = string, google::protobuf::internal::StringPieceField + // google::protobuf::Message & descendants. + template + const RepeatedPtrField& GetRepeatedPtrField( + const Message&, const FieldDescriptor*) const; + + // for T = string, google::protobuf::internal::StringPieceField + // google::protobuf::Message & descendants. + template + RepeatedPtrField* MutableRepeatedPtrField( + Message*, const FieldDescriptor*) const; + + // Extensions ---------------------------------------------------------------- // Try to find an extension of this message type by fully-qualified field // name. Returns NULL if no extension is known for this name or number. @@ -637,7 +693,26 @@ class LIBPROTOBUF_EXPORT Reflection { virtual const FieldDescriptor* FindKnownExtensionByNumber( int number) const = 0; + // --------------------------------------------------------------------------- + + protected: + // Obtain a pointer to a Repeated Field Structure and do some type checking: + // on field->cpp_type(), + // on field->field_option().ctype() (if ctype >= 0) + // of field->message_type() (if message_type != NULL). + // We use 1 routine rather than 4 (const vs mutable) x (scalar vs pointer). + virtual void* MutableRawRepeatedField( + Message* message, const FieldDescriptor* field, FieldDescriptor::CppType, + int ctype, const Descriptor* message_type) const = 0; + private: + // Special version for specialized implementations of string. We can't call + // MutableRawRepeatedField directly here because we don't have access to + // FieldOptions::* which are defined in descriptor.pb.h. Including that + // file here is not possible because it would cause a circular include cycle. + void* MutableRawRepeatedString( + Message* message, const FieldDescriptor* field, bool is_string) const; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection); }; @@ -654,7 +729,7 @@ class LIBPROTOBUF_EXPORT MessageFactory { // Calling this method twice with the same Descriptor returns the same // object. The returned object remains property of the factory. Also, any // objects created by calling the prototype's New() method share some data - // with the prototype, so these must be destoyed before the MessageFactory + // with the prototype, so these must be destroyed before the MessageFactory // is destroyed. // // The given descriptor must outlive the returned message, and hence must @@ -700,10 +775,91 @@ class LIBPROTOBUF_EXPORT MessageFactory { static void InternalRegisterGeneratedMessage(const Descriptor* descriptor, const Message* prototype); + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFactory); }; +#define DECLARE_GET_REPEATED_FIELD(TYPE) \ +template<> \ +LIBPROTOBUF_EXPORT \ +const RepeatedField& Reflection::GetRepeatedField( \ + const Message& message, const FieldDescriptor* field) const; \ + \ +template<> \ +RepeatedField* Reflection::MutableRepeatedField( \ + Message* message, const FieldDescriptor* field) const; + +DECLARE_GET_REPEATED_FIELD(int32) +DECLARE_GET_REPEATED_FIELD(int64) +DECLARE_GET_REPEATED_FIELD(uint32) +DECLARE_GET_REPEATED_FIELD(uint64) +DECLARE_GET_REPEATED_FIELD(float) +DECLARE_GET_REPEATED_FIELD(double) +DECLARE_GET_REPEATED_FIELD(bool) + +#undef DECLARE_GET_REPEATED_FIELD + +// ============================================================================= +// Implementation details for {Get,Mutable}RawRepeatedPtrField. We provide +// specializations for , and and handle +// everything else with the default template which will match any type having +// a method with signature "static const google::protobuf::Descriptor* descriptor()". +// Such a type presumably is a descendant of google::protobuf::Message. + +template<> +inline const RepeatedPtrField& Reflection::GetRepeatedPtrField( + const Message& message, const FieldDescriptor* field) const { + return *static_cast* >( + MutableRawRepeatedString(const_cast(&message), field, true)); +} + +template<> +inline RepeatedPtrField* Reflection::MutableRepeatedPtrField( + Message* message, const FieldDescriptor* field) const { + return static_cast* >( + MutableRawRepeatedString(message, field, true)); +} + + +// ----- + +template<> +inline const RepeatedPtrField& Reflection::GetRepeatedPtrField( + const Message& message, const FieldDescriptor* field) const { + return *static_cast* >( + MutableRawRepeatedField(const_cast(&message), field, + FieldDescriptor::CPPTYPE_MESSAGE, -1, + NULL)); +} + +template<> +inline RepeatedPtrField* Reflection::MutableRepeatedPtrField( + Message* message, const FieldDescriptor* field) const { + return static_cast* >( + MutableRawRepeatedField(message, field, + FieldDescriptor::CPPTYPE_MESSAGE, -1, + NULL)); +} + +template +inline const RepeatedPtrField& Reflection::GetRepeatedPtrField( + const Message& message, const FieldDescriptor* field) const { + return *static_cast* >( + MutableRawRepeatedField(const_cast(&message), field, + FieldDescriptor::CPPTYPE_MESSAGE, -1, + PB::default_instance().GetDescriptor())); +} + +template +inline RepeatedPtrField* Reflection::MutableRepeatedPtrField( + Message* message, const FieldDescriptor* field) const { + return static_cast* >( + MutableRawRepeatedField(message, field, + FieldDescriptor::CPPTYPE_MESSAGE, -1, + PB::default_instance().GetDescriptor())); +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index 7c8f37d..af6b301 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -37,8 +37,8 @@ #include #include #include -#include -#include +#include +#include namespace google { namespace protobuf { @@ -278,7 +278,8 @@ bool MessageLite::AppendPartialToString(string* output) const { int old_size = output->size(); int byte_size = ByteSize(); STLStringResizeUninitialized(output, old_size + byte_size); - uint8* start = reinterpret_cast(string_as_array(output) + old_size); + uint8* start = + reinterpret_cast(io::mutable_string_data(output) + old_size); uint8* end = SerializeWithCachedSizesToArray(start); if (end - start != byte_size) { ByteSizeConsistencyError(byte_size, ByteSize(), end - start); diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index ebf4ba3..a976e5a 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -40,11 +40,17 @@ #define GOOGLE_PROTOBUF_MESSAGE_LITE_H__ #include -#include namespace google { namespace protobuf { +namespace io { + class CodedInputStream; + class CodedOutputStream; + class ZeroCopyInputStream; + class ZeroCopyOutputStream; +} + // Interface to light weight protocol messages. // // This interface is implemented by all protocol message objects. Non-lite @@ -103,7 +109,8 @@ class LIBPROTOBUF_EXPORT MessageLite { // Parsing --------------------------------------------------------- // Methods for parsing in protocol buffer format. Most of these are - // just simple wrappers around MergeFromCodedStream(). + // just simple wrappers around MergeFromCodedStream(). Clear() will be called + // before merging the input. // Fill the message with a protocol buffer parsed from the given input // stream. Returns false on a read error or if the input is in the @@ -158,6 +165,7 @@ class LIBPROTOBUF_EXPORT MessageLite { // followed by IsInitialized(). virtual bool MergePartialFromCodedStream(io::CodedInputStream* input) = 0; + // Serialization --------------------------------------------------- // Methods for serializing in protocol buffer format. Most of these // are just simple wrappers around ByteSize() and SerializeWithCachedSizes(). diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc index 33b9e77..8b6fd6f 100644 --- a/src/google/protobuf/message_unittest.cc +++ b/src/google/protobuf/message_unittest.cc @@ -45,7 +45,6 @@ #include #include -#include #include #include #include @@ -53,6 +52,7 @@ #include #include +#include #include #include @@ -205,7 +205,7 @@ TEST(MessageTest, InitializationErrorString) { EXPECT_EQ("a, b, c", message.InitializationErrorString()); } -#ifdef GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet. +#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet. TEST(MessageTest, SerializeFailsIfNotInitialized) { unittest::TestRequired message; @@ -222,7 +222,25 @@ TEST(MessageTest, CheckInitialized) { "fields: a, b, c"); } -#endif // GTEST_HAS_DEATH_TEST +TEST(MessageTest, CheckOverflow) { + unittest::TestAllTypes message; + // Create a message with size just over 2GB. This triggers integer overflow + // when computing message size. + const string data(1024, 'x'); + Cord one_megabyte; + for (int i = 0; i < 1024; i++) { + one_megabyte.Append(data); + } + + for (int i = 0; i < 2 * 1024 + 1; ++i) { + message.add_repeated_cord()->CopyFrom(one_megabyte); + } + + Cord serialized; + EXPECT_FALSE(message.AppendToCord(&serialized)); +} + +#endif // PROTOBUF_HAS_DEATH_TEST TEST(MessageTest, BypassInitializationCheckOnSerialize) { unittest::TestRequired message; @@ -257,6 +275,133 @@ TEST(MessageTest, ParseFailsOnInvalidMessageEnd) { EXPECT_FALSE(message.ParseFromArray("\014", 1)); } +namespace { + +void ExpectMessageMerged(const unittest::TestAllTypes& message) { + EXPECT_EQ(3, message.optional_int32()); + EXPECT_EQ(2, message.optional_int64()); + EXPECT_EQ("hello", message.optional_string()); +} + +void AssignParsingMergeMessages( + unittest::TestAllTypes* msg1, + unittest::TestAllTypes* msg2, + unittest::TestAllTypes* msg3) { + msg1->set_optional_int32(1); + msg2->set_optional_int64(2); + msg3->set_optional_int32(3); + msg3->set_optional_string("hello"); +} + +} // namespace + +// Test that if an optional or required message/group field appears multiple +// times in the input, they need to be merged. +TEST(MessageTest, ParsingMerge) { + unittest::TestParsingMerge::RepeatedFieldsGenerator generator; + unittest::TestAllTypes* msg1; + unittest::TestAllTypes* msg2; + unittest::TestAllTypes* msg3; + +#define ASSIGN_REPEATED_FIELD(FIELD) \ + msg1 = generator.add_##FIELD(); \ + msg2 = generator.add_##FIELD(); \ + msg3 = generator.add_##FIELD(); \ + AssignParsingMergeMessages(msg1, msg2, msg3) + + ASSIGN_REPEATED_FIELD(field1); + ASSIGN_REPEATED_FIELD(field2); + ASSIGN_REPEATED_FIELD(field3); + ASSIGN_REPEATED_FIELD(ext1); + ASSIGN_REPEATED_FIELD(ext2); + +#undef ASSIGN_REPEATED_FIELD +#define ASSIGN_REPEATED_GROUP(FIELD) \ + msg1 = generator.add_##FIELD()->mutable_field1(); \ + msg2 = generator.add_##FIELD()->mutable_field1(); \ + msg3 = generator.add_##FIELD()->mutable_field1(); \ + AssignParsingMergeMessages(msg1, msg2, msg3) + + ASSIGN_REPEATED_GROUP(group1); + ASSIGN_REPEATED_GROUP(group2); + +#undef ASSIGN_REPEATED_GROUP + + string buffer; + generator.SerializeToString(&buffer); + unittest::TestParsingMerge parsing_merge; + parsing_merge.ParseFromString(buffer); + + // Required and optional fields should be merged. + ExpectMessageMerged(parsing_merge.required_all_types()); + ExpectMessageMerged(parsing_merge.optional_all_types()); + ExpectMessageMerged( + parsing_merge.optionalgroup().optional_group_all_types()); + ExpectMessageMerged( + parsing_merge.GetExtension(unittest::TestParsingMerge::optional_ext)); + + // Repeated fields should not be merged. + EXPECT_EQ(3, parsing_merge.repeated_all_types_size()); + EXPECT_EQ(3, parsing_merge.repeatedgroup_size()); + EXPECT_EQ(3, parsing_merge.ExtensionSize( + unittest::TestParsingMerge::repeated_ext)); +} + +TEST(MessageTest, MergeFrom) { + unittest::TestAllTypes source; + unittest::TestAllTypes dest; + + // Optional fields + source.set_optional_int32(1); // only source + source.set_optional_int64(2); // both source and dest + dest.set_optional_int64(3); + dest.set_optional_uint32(4); // only dest + + // Optional fields with defaults + source.set_default_int32(13); // only source + source.set_default_int64(14); // both source and dest + dest.set_default_int64(15); + dest.set_default_uint32(16); // only dest + + // Repeated fields + source.add_repeated_int32(5); // only source + source.add_repeated_int32(6); + source.add_repeated_int64(7); // both source and dest + source.add_repeated_int64(8); + dest.add_repeated_int64(9); + dest.add_repeated_int64(10); + dest.add_repeated_uint32(11); // only dest + dest.add_repeated_uint32(12); + + dest.MergeFrom(source); + + // Optional fields: source overwrites dest if source is specified + EXPECT_EQ(1, dest.optional_int32()); // only source: use source + EXPECT_EQ(2, dest.optional_int64()); // source and dest: use source + EXPECT_EQ(4, dest.optional_uint32()); // only dest: use dest + EXPECT_EQ(0, dest.optional_uint64()); // neither: use default + + // Optional fields with defaults + EXPECT_EQ(13, dest.default_int32()); // only source: use source + EXPECT_EQ(14, dest.default_int64()); // source and dest: use source + EXPECT_EQ(16, dest.default_uint32()); // only dest: use dest + EXPECT_EQ(44, dest.default_uint64()); // neither: use default + + // Repeated fields: concatenate source onto the end of dest + ASSERT_EQ(2, dest.repeated_int32_size()); + EXPECT_EQ(5, dest.repeated_int32(0)); + EXPECT_EQ(6, dest.repeated_int32(1)); + ASSERT_EQ(4, dest.repeated_int64_size()); + EXPECT_EQ(9, dest.repeated_int64(0)); + EXPECT_EQ(10, dest.repeated_int64(1)); + EXPECT_EQ(7, dest.repeated_int64(2)); + EXPECT_EQ(8, dest.repeated_int64(3)); + ASSERT_EQ(2, dest.repeated_uint32_size()); + EXPECT_EQ(11, dest.repeated_uint32(0)); + EXPECT_EQ(12, dest.repeated_uint32(1)); + ASSERT_EQ(0, dest.repeated_uint64_size()); +} + TEST(MessageFactoryTest, GeneratedFactoryLookup) { EXPECT_EQ( MessageFactory::generated_factory()->GetPrototype( @@ -277,5 +422,6 @@ TEST(MessageFactoryTest, GeneratedFactoryUnknownType) { MessageFactory::generated_factory()->GetPrototype(descriptor) == NULL); } + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/reflection_ops.cc b/src/google/protobuf/reflection_ops.cc index 897c0d7..8993a24 100644 --- a/src/google/protobuf/reflection_ops.cc +++ b/src/google/protobuf/reflection_ops.cc @@ -32,8 +32,12 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include +#include + #include #include +#include #include #include @@ -52,7 +56,9 @@ void ReflectionOps::Merge(const Message& from, Message* to) { const Descriptor* descriptor = from.GetDescriptor(); GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor) - << "Tried to merge messages of different types."; + << "Tried to merge messages of different types " + << "(merge " << descriptor->full_name() + << " to " << to->GetDescriptor()->full_name() << ")"; const Reflection* from_reflection = from.GetReflection(); const Reflection* to_reflection = to->GetReflection(); @@ -151,11 +157,12 @@ bool ReflectionOps::IsInitialized(const Message& message) { for (int i = 0; i < fields.size(); i++) { const FieldDescriptor* field = fields[i]; if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (field->is_repeated()) { int size = reflection->FieldSize(message, field); - for (int i = 0; i < size; i++) { - if (!reflection->GetRepeatedMessage(message, field, i) + for (int j = 0; j < size; j++) { + if (!reflection->GetRepeatedMessage(message, field, j) .IsInitialized()) { return false; } @@ -183,8 +190,8 @@ void ReflectionOps::DiscardUnknownFields(Message* message) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (field->is_repeated()) { int size = reflection->FieldSize(*message, field); - for (int i = 0; i < size; i++) { - reflection->MutableRepeatedMessage(message, field, i) + for (int j = 0; j < size; j++) { + reflection->MutableRepeatedMessage(message, field, j) ->DiscardUnknownFields(); } } else { @@ -240,11 +247,11 @@ void ReflectionOps::FindInitializationErrors( if (field->is_repeated()) { int size = reflection->FieldSize(message, field); - for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { const Message& sub_message = - reflection->GetRepeatedMessage(message, field, i); + reflection->GetRepeatedMessage(message, field, j); FindInitializationErrors(sub_message, - SubMessagePrefix(prefix, field, i), + SubMessagePrefix(prefix, field, j), errors); } } else { diff --git a/src/google/protobuf/reflection_ops.h b/src/google/protobuf/reflection_ops.h index 355a0a5..60165c2 100644 --- a/src/google/protobuf/reflection_ops.h +++ b/src/google/protobuf/reflection_ops.h @@ -38,6 +38,7 @@ #ifndef GOOGLE_PROTOBUF_REFLECTION_OPS_H__ #define GOOGLE_PROTOBUF_REFLECTION_OPS_H__ +#include #include namespace google { diff --git a/src/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc index 1cd56f1..898c20c 100644 --- a/src/google/protobuf/reflection_ops_unittest.cc +++ b/src/google/protobuf/reflection_ops_unittest.cc @@ -78,6 +78,18 @@ TEST(ReflectionOpsTest, CopyExtensions) { TestUtil::ExpectAllExtensionsSet(message2); } +TEST(ReflectionOpsTest, CopyOneof) { + unittest::TestOneof2 message, message2; + TestUtil::SetOneof1(&message); + ReflectionOps::Copy(message, &message2); + TestUtil::ExpectOneofSet1(message2); + + TestUtil::SetOneof2(&message); + TestUtil::ExpectOneofSet2(message); + ReflectionOps::Copy(message, &message2); + TestUtil::ExpectOneofSet2(message2); +} + TEST(ReflectionOpsTest, Merge) { // Note: Copy is implemented in terms of Merge() so technically the Copy // test already tested most of this. @@ -152,7 +164,25 @@ TEST(ReflectionOpsTest, MergeUnknown) { EXPECT_EQ(2, message1.unknown_fields().field(1).varint()); } -#ifdef GTEST_HAS_DEATH_TEST +TEST(ReflectionOpsTest, MergeOneof) { + unittest::TestOneof2 message1, message2; + TestUtil::SetOneof1(&message1); + + // Merge to empty message + ReflectionOps::Merge(message1, &message2); + TestUtil::ExpectOneofSet1(message2); + + // Merge with the same oneof fields + ReflectionOps::Merge(message1, &message2); + TestUtil::ExpectOneofSet1(message2); + + // Merge with different oneof fields + TestUtil::SetOneof2(&message1); + ReflectionOps::Merge(message1, &message2); + TestUtil::ExpectOneofSet2(message2); +} + +#ifdef PROTOBUF_HAS_DEATH_TEST TEST(ReflectionOpsTest, MergeFromSelf) { // Note: Copy is implemented in terms of Merge() so technically the Copy @@ -165,7 +195,7 @@ TEST(ReflectionOpsTest, MergeFromSelf) { "&from"); } -#endif // GTEST_HAS_DEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST TEST(ReflectionOpsTest, Clear) { unittest::TestAllTypes message; @@ -220,6 +250,23 @@ TEST(ReflectionOpsTest, ClearUnknown) { EXPECT_EQ(0, message.unknown_fields().field_count()); } +TEST(ReflectionOpsTest, ClearOneof) { + unittest::TestOneof2 message; + + TestUtil::ExpectOneofClear(message); + TestUtil::SetOneof1(&message); + TestUtil::ExpectOneofSet1(message); + ReflectionOps::Clear(&message); + TestUtil::ExpectOneofClear(message); + + TestUtil::SetOneof1(&message); + TestUtil::ExpectOneofSet1(message); + TestUtil::SetOneof2(&message); + TestUtil::ExpectOneofSet2(message); + ReflectionOps::Clear(&message); + TestUtil::ExpectOneofClear(message); +} + TEST(ReflectionOpsTest, DiscardUnknownFields) { unittest::TestAllTypes message; TestUtil::SetAllFields(&message); @@ -354,10 +401,26 @@ TEST(ReflectionOpsTest, ExtensionIsInitialized) { EXPECT_TRUE(ReflectionOps::IsInitialized(message)); } +TEST(ReflectionOpsTest, OneofIsInitialized) { + unittest::TestRequiredOneof message; + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + + message.mutable_foo_message(); + EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + + message.set_foo_int(1); + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + + message.mutable_foo_message(); + EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + message.mutable_foo_message()->set_required_double(0.1); + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); +} + static string FindInitializationErrors(const Message& message) { vector errors; ReflectionOps::FindInitializationErrors(message, "", &errors); - return JoinStrings(errors, ","); + return Join(errors, ","); } TEST(ReflectionOpsTest, FindInitializationErrors) { @@ -399,6 +462,13 @@ TEST(ReflectionOpsTest, FindExtensionInitializationErrors) { FindInitializationErrors(message)); } +TEST(ReflectionOpsTest, FindOneofInitializationErrors) { + unittest::TestRequiredOneof message; + message.mutable_foo_message(); + EXPECT_EQ("foo_message.required_double", + FindInitializationErrors(message)); +} + } // namespace } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc index f7beb11..2c1f74c 100644 --- a/src/google/protobuf/repeated_field.cc +++ b/src/google/protobuf/repeated_field.cc @@ -32,53 +32,45 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include + #include #include namespace google { namespace protobuf { + namespace internal { void RepeatedPtrFieldBase::Reserve(int new_size) { if (total_size_ >= new_size) return; void** old_elements = elements_; - total_size_ = max(total_size_ * 2, new_size); + total_size_ = max(kMinRepeatedFieldAllocationSize, + max(total_size_ * 2, new_size)); elements_ = new void*[total_size_]; - memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0])); - if (old_elements != initial_space_) { + if (old_elements != NULL) { + memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0])); delete [] old_elements; } } void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) { + if (this == other) return; void** swap_elements = elements_; int swap_current_size = current_size_; int swap_allocated_size = allocated_size_; int swap_total_size = total_size_; - // We may not be using initial_space_ but it's not worth checking. Just - // copy it anyway. - void* swap_initial_space[kInitialSize]; - memcpy(swap_initial_space, initial_space_, sizeof(initial_space_)); elements_ = other->elements_; current_size_ = other->current_size_; allocated_size_ = other->allocated_size_; total_size_ = other->total_size_; - memcpy(initial_space_, other->initial_space_, sizeof(initial_space_)); other->elements_ = swap_elements; other->current_size_ = swap_current_size; other->allocated_size_ = swap_allocated_size; other->total_size_ = swap_total_size; - memcpy(other->initial_space_, swap_initial_space, sizeof(swap_initial_space)); - - if (elements_ == other->initial_space_) { - elements_ = initial_space_; - } - if (other->elements_ == initial_space_) { - other->elements_ = other->initial_space_; - } } string* StringTypeHandlerBase::New() { @@ -88,8 +80,8 @@ void StringTypeHandlerBase::Delete(string* value) { delete value; } +} // namespace internal -} // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index defdefe..00e8311 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -46,24 +46,55 @@ #ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__ #define GOOGLE_PROTOBUF_REPEATED_FIELD_H__ +#ifdef _MSC_VER +// This is required for min/max on VS2013 only. +#include +#endif + #include #include #include +#include +#include #include namespace google { +namespace upb { +namespace google_opensource { +class GMR_Handlers; +} // namespace google_opensource +} // namespace upb + namespace protobuf { class Message; namespace internal { -// We need this (from generated_message_reflection.cc). -LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str); +static const int kMinRepeatedFieldAllocationSize = 4; + +// A utility function for logging that doesn't need any template types. +void LogIndexOutOfBounds(int index, int size); +template +inline int CalculateReserve(Iter begin, Iter end, std::forward_iterator_tag) { + return std::distance(begin, end); +} + +template +inline int CalculateReserve(Iter begin, Iter end, std::input_iterator_tag) { + return -1; +} + +template +inline int CalculateReserve(Iter begin, Iter end) { + typedef typename std::iterator_traits::iterator_category Category; + return CalculateReserve(begin, end, Category()); +} } // namespace internal + // RepeatedField is used to represent repeated fields of a primitive type (in // other words, everything except strings and nested Messages). Most users will // not ever use a RepeatedField directly; they will use the get-by-index, @@ -72,8 +103,14 @@ template class RepeatedField { public: RepeatedField(); + RepeatedField(const RepeatedField& other); + template + RepeatedField(Iter begin, const Iter& end); ~RepeatedField(); + RepeatedField& operator=(const RepeatedField& other); + + bool empty() const; int size() const; const Element& Get(int index) const; @@ -82,14 +119,17 @@ class RepeatedField { void Add(const Element& value); Element* Add(); // Remove the last element in the array. - // We don't provide a way to remove any element other than the last - // because it invites inefficient use, such as O(n^2) filtering loops - // that should have been O(n). If you want to remove an element other - // than the last, the best way to do it is to re-arrange the elements - // so that the one you want removed is at the end, then call RemoveLast(). void RemoveLast(); + + // Extract elements with indices in "[start .. start+num-1]". + // Copy them into "elements[0 .. num-1]" if "elements" is not NULL. + // Caution: implementation also moves elements with indices [start+num ..]. + // Calling this routine inside a loop can cause quadratic behavior. + void ExtractSubrange(int start, int num, Element* elements); + void Clear(); void MergeFrom(const RepeatedField& other); + void CopyFrom(const RepeatedField& other); // Reserve space to expand the field to at least the given size. If the // array is grown, it will always be at least doubled in size. @@ -102,6 +142,11 @@ class RepeatedField { Element* AddAlreadyReserved(); int Capacity() const; + // Like STL resize. Uses value to fill appended elements. + // Like Truncate() if new_size <= size(), otherwise this is + // O(new_size - size()). + void Resize(int new_size, const Element& value); + // Gets the underlying array. This pointer is possibly invalidated by // any add or remove operation. Element* mutable_data(); @@ -116,27 +161,46 @@ class RepeatedField { // STL-like iterator support typedef Element* iterator; typedef const Element* const_iterator; + typedef Element value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef int size_type; + typedef ptrdiff_t difference_type; iterator begin(); const_iterator begin() const; iterator end(); const_iterator end() const; + // Reverse iterator support + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + reverse_iterator rbegin() { + return reverse_iterator(end()); + } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { + return reverse_iterator(begin()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + // Returns the number of bytes used by the repeated field, excluding // sizeof(*this) int SpaceUsedExcludingSelf() const; private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedField); - - static const int kInitialSize = 4; + static const int kInitialSize = 0; Element* elements_; int current_size_; int total_size_; - Element initial_space_[kInitialSize]; - // Move the contents of |from| into |to|, possibly clobbering |from| in the // process. For primitive types this is just a memcpy(), but it could be // specialized for non-primitive types to, say, swap each element instead. @@ -148,7 +212,21 @@ class RepeatedField { namespace internal { template class RepeatedPtrIterator; -template class RepeatedPtrOverPtrsIterator; +template class RepeatedPtrOverPtrsIterator; +} // namespace internal + +namespace internal { + +// This is a helper template to copy an array of elements effeciently when they +// have a trivial copy constructor, and correctly otherwise. This really +// shouldn't be necessary, but our compiler doesn't optimize std::copy very +// effectively. +template ::value> +struct ElementCopier { + void operator()(Element to[], const Element from[], int array_size); +}; + } // namespace internal namespace internal { @@ -183,12 +261,17 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { // use of AddFromCleared(), which is not part of the public interface. friend class ExtensionSet; + // To parse directly into a proto2 generated class, the upb class GMR_Handlers + // needs to be able to modify a RepeatedPtrFieldBase directly. + friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers; + RepeatedPtrFieldBase(); // Must be called from destructor. template void Destroy(); + bool empty() const; int size() const; template @@ -203,6 +286,16 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { void Clear(); template void MergeFrom(const RepeatedPtrFieldBase& other); + template + void CopyFrom(const RepeatedPtrFieldBase& other); + + void CloseGap(int start, int num) { + // Close up a gap of "num" elements starting at offset "start". + for (int i = start + num; i < allocated_size_; ++i) + elements_[i - num] = elements_[i]; + current_size_ -= num; + allocated_size_ -= num; + } void Reserve(int new_size); @@ -243,17 +336,13 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { typename TypeHandler::Type* ReleaseCleared(); private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase); - - static const int kInitialSize = 4; + static const int kInitialSize = 0; void** elements_; int current_size_; int allocated_size_; int total_size_; - void* initial_space_[kInitialSize]; - template static inline typename TypeHandler::Type* cast(void* element) { return reinterpret_cast(element); @@ -262,6 +351,8 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { static inline const typename TypeHandler::Type* cast(const void* element) { return reinterpret_cast(element); } + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase); }; template @@ -275,6 +366,7 @@ class GenericTypeHandler { to->MergeFrom(from); } static int SpaceUsed(const GenericType& value) { return value.SpaceUsed(); } + static const Type& default_instance() { return Type::default_instance(); } }; template <> @@ -283,6 +375,25 @@ inline void GenericTypeHandler::Merge( to->CheckTypeAndMergeFrom(from); } +template <> +inline const MessageLite& GenericTypeHandler::default_instance() { + // Yes, the behavior of the code is undefined, but this function is only + // called when we're already deep into the world of undefined, because the + // caller called Get(index) out of bounds. + MessageLite* null = NULL; + return *null; +} + +template <> +inline const Message& GenericTypeHandler::default_instance() { + // Yes, the behavior of the code is undefined, but this function is only + // called when we're already deep into the world of undefined, because the + // caller called Get(index) out of bounds. + Message* null = NULL; + return *null; +} + + // HACK: If a class is declared as DLL-exported in MSVC, it insists on // generating copies of all its methods -- even inline ones -- to include // in the DLL. But SpaceUsed() calls StringSpaceUsedExcludingSelf() which @@ -298,6 +409,9 @@ class LIBPROTOBUF_EXPORT StringTypeHandlerBase { static void Delete(string* value); static void Clear(string* value) { value->clear(); } static void Merge(const string& from, string* to) { *to = from; } + static const Type& default_instance() { + return ::google::protobuf::internal::GetEmptyString(); + } }; class StringTypeHandler : public StringTypeHandlerBase { @@ -316,17 +430,32 @@ template class RepeatedPtrField : public internal::RepeatedPtrFieldBase { public: RepeatedPtrField(); - + RepeatedPtrField(const RepeatedPtrField& other); + template + RepeatedPtrField(Iter begin, const Iter& end); ~RepeatedPtrField(); + RepeatedPtrField& operator=(const RepeatedPtrField& other); + + bool empty() const; int size() const; const Element& Get(int index) const; Element* Mutable(int index); Element* Add(); - void RemoveLast(); // Remove the last element in the array. + + // Remove the last element in the array. + // Ownership of the element is retained by the array. + void RemoveLast(); + + // Delete elements with indices in the range [start .. start+num-1]. + // Caution: implementation moves all elements with indices [start+num .. ]. + // Calling this routine inside a loop can cause quadratic behavior. + void DeleteSubrange(int start, int num); + void Clear(); void MergeFrom(const RepeatedPtrField& other); + void CopyFrom(const RepeatedPtrField& other); // Reserve space to expand the field to at least the given size. This only // resizes the pointer array; it doesn't allocate any objects. If the @@ -349,47 +478,79 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase { // STL-like iterator support typedef internal::RepeatedPtrIterator iterator; typedef internal::RepeatedPtrIterator const_iterator; + typedef Element value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef int size_type; + typedef ptrdiff_t difference_type; iterator begin(); const_iterator begin() const; iterator end(); const_iterator end() const; + // Reverse iterator support + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + reverse_iterator rbegin() { + return reverse_iterator(end()); + } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { + return reverse_iterator(begin()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + // Custom STL-like iterator that iterates over and returns the underlying // pointers to Element rather than Element itself. - typedef internal::RepeatedPtrOverPtrsIterator pointer_iterator; + typedef internal::RepeatedPtrOverPtrsIterator + pointer_iterator; + typedef internal::RepeatedPtrOverPtrsIterator + const_pointer_iterator; pointer_iterator pointer_begin(); + const_pointer_iterator pointer_begin() const; pointer_iterator pointer_end(); + const_pointer_iterator pointer_end() const; // Returns (an estimate of) the number of bytes used by the repeated field, // excluding sizeof(*this). int SpaceUsedExcludingSelf() const; - // The spaced used just by the pointer array, not counting the objects pointed - // at. Returns zero if the array is inlined (i.e. initial_space_ is being - // used). - int SpaceUsedByArray() const; - // Advanced memory management -------------------------------------- - // When hardcore memory management becomes necessary -- as it often + // When hardcore memory management becomes necessary -- as it sometimes // does here at Google -- the following methods may be useful. // Add an already-allocated object, passing ownership to the // RepeatedPtrField. void AddAllocated(Element* value); - // Remove the last element and return it, passing ownership to the - // caller. + // Remove the last element and return it, passing ownership to the caller. // Requires: size() > 0 Element* ReleaseLast(); + // Extract elements with indices in the range "[start .. start+num-1]". + // The caller assumes ownership of the extracted elements and is responsible + // for deleting them when they are no longer needed. + // If "elements" is non-NULL, then pointers to the extracted elements + // are stored in "elements[0 .. num-1]" for the convenience of the caller. + // If "elements" is NULL, then the caller must use some other mechanism + // to perform any further operations (like deletion) on these elements. + // Caution: implementation also moves elements with indices [start+num ..]. + // Calling this routine inside a loop can cause quadratic behavior. + void ExtractSubrange(int start, int num, Element** elements); + // When elements are removed by calls to RemoveLast() or Clear(), they // are not actually freed. Instead, they are cleared and kept so that // they can be reused later. This can save lots of CPU time when // repeatedly reusing a protocol message for similar purposes. // - // Really, extremely hardcore programs may actually want to manipulate - // these objects to better-optimize memory management. These methods - // allow that. + // Hardcore programs may choose to manipulate these cleared objects + // to better optimize memory management using the following routines. // Get the number of cleared objects that are currently being kept // around for reuse. @@ -410,28 +571,63 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase { // methods on RepeatedPtrFieldBase. class TypeHandler; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrField); }; // implementation ==================================================== template inline RepeatedField::RepeatedField() - : elements_(initial_space_), + : elements_(NULL), current_size_(0), total_size_(kInitialSize) { } template -RepeatedField::~RepeatedField() { - if (elements_ != initial_space_) { - delete [] elements_; +inline RepeatedField::RepeatedField(const RepeatedField& other) + : elements_(NULL), + current_size_(0), + total_size_(kInitialSize) { + CopyFrom(other); +} + +template +template +inline RepeatedField::RepeatedField(Iter begin, const Iter& end) + : elements_(NULL), + current_size_(0), + total_size_(kInitialSize) { + int reserve = internal::CalculateReserve(begin, end); + if (reserve != -1) { + Reserve(reserve); + for (; begin != end; ++begin) { + AddAlreadyReserved(*begin); + } + } else { + for (; begin != end; ++begin) { + Add(*begin); + } } } template +RepeatedField::~RepeatedField() { + delete [] elements_; +} + +template +inline RepeatedField& +RepeatedField::operator=(const RepeatedField& other) { + if (this != &other) + CopyFrom(other); + return *this; +} + +template +inline bool RepeatedField::empty() const { + return current_size_ == 0; +} + +template inline int RepeatedField::size() const { return current_size_; } @@ -453,20 +649,33 @@ inline Element* RepeatedField::AddAlreadyReserved() { return &elements_[current_size_++]; } +template +inline void RepeatedField::Resize(int new_size, const Element& value) { + GOOGLE_DCHECK_GE(new_size, 0); + if (new_size > size()) { + Reserve(new_size); + std::fill(&elements_[current_size_], &elements_[new_size], value); + } + current_size_ = new_size; +} + template inline const Element& RepeatedField::Get(int index) const { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); return elements_[index]; } template inline Element* RepeatedField::Mutable(int index) { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); return elements_ + index; } template inline void RepeatedField::Set(int index, const Element& value) { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); elements_[index] = value; } @@ -490,15 +699,46 @@ inline void RepeatedField::RemoveLast() { } template +void RepeatedField::ExtractSubrange( + int start, int num, Element* elements) { + GOOGLE_DCHECK_GE(start, 0); + GOOGLE_DCHECK_GE(num, 0); + GOOGLE_DCHECK_LE(start + num, this->size()); + + // Save the values of the removed elements if requested. + if (elements != NULL) { + for (int i = 0; i < num; ++i) + elements[i] = this->Get(i + start); + } + + // Slide remaining elements down to fill the gap. + if (num > 0) { + for (int i = start + num; i < this->size(); ++i) + this->Set(i - num, this->Get(i)); + this->Truncate(this->size() - num); + } +} + +template inline void RepeatedField::Clear() { current_size_ = 0; } template inline void RepeatedField::MergeFrom(const RepeatedField& other) { - Reserve(current_size_ + other.current_size_); - CopyArray(elements_ + current_size_, other.elements_, other.current_size_); - current_size_ += other.current_size_; + GOOGLE_CHECK_NE(&other, this); + if (other.current_size_ != 0) { + Reserve(current_size_ + other.current_size_); + CopyArray(elements_ + current_size_, other.elements_, other.current_size_); + current_size_ += other.current_size_; + } +} + +template +inline void RepeatedField::CopyFrom(const RepeatedField& other) { + if (&other == this) return; + Clear(); + MergeFrom(other); } template @@ -514,35 +754,24 @@ inline const Element* RepeatedField::data() const { template void RepeatedField::Swap(RepeatedField* other) { + if (this == other) return; Element* swap_elements = elements_; int swap_current_size = current_size_; int swap_total_size = total_size_; - // We may not be using initial_space_ but it's not worth checking. Just - // copy it anyway. - Element swap_initial_space[kInitialSize]; - MoveArray(swap_initial_space, initial_space_, kInitialSize); elements_ = other->elements_; current_size_ = other->current_size_; total_size_ = other->total_size_; - MoveArray(initial_space_, other->initial_space_, kInitialSize); other->elements_ = swap_elements; other->current_size_ = swap_current_size; other->total_size_ = swap_total_size; - MoveArray(other->initial_space_, swap_initial_space, kInitialSize); - - if (elements_ == other->initial_space_) { - elements_ = initial_space_; - } - if (other->elements_ == initial_space_) { - other->elements_ = other->initial_space_; - } } template void RepeatedField::SwapElements(int index1, int index2) { - std::swap(elements_[index1], elements_[index2]); + using std::swap; // enable ADL with fallback + swap(elements_[index1], elements_[index2]); } template @@ -568,20 +797,21 @@ RepeatedField::end() const { template inline int RepeatedField::SpaceUsedExcludingSelf() const { - return (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0; + return (elements_ != NULL) ? total_size_ * sizeof(elements_[0]) : 0; } -// Avoid inlining of Reserve(): new, memcpy, and delete[] lead to a significant +// Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant // amount of code bloat. template void RepeatedField::Reserve(int new_size) { if (total_size_ >= new_size) return; Element* old_elements = elements_; - total_size_ = max(total_size_ * 2, new_size); + total_size_ = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize, + max(total_size_ * 2, new_size)); elements_ = new Element[total_size_]; - MoveArray(elements_, old_elements, current_size_); - if (old_elements != initial_space_) { + if (old_elements != NULL) { + MoveArray(elements_, old_elements, current_size_); delete [] old_elements; } } @@ -594,23 +824,40 @@ inline void RepeatedField::Truncate(int new_size) { template inline void RepeatedField::MoveArray( - Element to[], Element from[], int size) { - memcpy(to, from, size * sizeof(Element)); + Element to[], Element from[], int array_size) { + CopyArray(to, from, array_size); } template inline void RepeatedField::CopyArray( - Element to[], const Element from[], int size) { - memcpy(to, from, size * sizeof(Element)); + Element to[], const Element from[], int array_size) { + internal::ElementCopier()(to, from, array_size); } +namespace internal { + +template +void ElementCopier::operator()( + Element to[], const Element from[], int array_size) { + std::copy(from, from + array_size, to); +} + +template +struct ElementCopier { + void operator()(Element to[], const Element from[], int array_size) { + memcpy(to, from, array_size * sizeof(Element)); + } +}; + +} // namespace internal + // ------------------------------------------------------------------- namespace internal { inline RepeatedPtrFieldBase::RepeatedPtrFieldBase() - : elements_(initial_space_), + : elements_(NULL), current_size_(0), allocated_size_(0), total_size_(kInitialSize) { @@ -621,26 +868,30 @@ void RepeatedPtrFieldBase::Destroy() { for (int i = 0; i < allocated_size_; i++) { TypeHandler::Delete(cast(elements_[i])); } - if (elements_ != initial_space_) { - delete [] elements_; - } + delete [] elements_; +} + +inline bool RepeatedPtrFieldBase::empty() const { + return current_size_ == 0; } inline int RepeatedPtrFieldBase::size() const { return current_size_; } - template inline const typename TypeHandler::Type& RepeatedPtrFieldBase::Get(int index) const { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); return *cast(elements_[index]); } + template inline typename TypeHandler::Type* RepeatedPtrFieldBase::Mutable(int index) { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); return cast(elements_[index]); } @@ -651,8 +902,8 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add() { return cast(elements_[current_size_++]); } if (allocated_size_ == total_size_) Reserve(total_size_ + 1); - ++allocated_size_; typename TypeHandler::Type* result = TypeHandler::New(); + ++allocated_size_; elements_[current_size_++] = result; return result; } @@ -673,12 +924,20 @@ void RepeatedPtrFieldBase::Clear() { template inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) { + GOOGLE_CHECK_NE(&other, this); Reserve(current_size_ + other.current_size_); for (int i = 0; i < other.current_size_; i++) { - TypeHandler::Merge(other.Get(i), Add()); + TypeHandler::Merge(other.template Get(i), Add()); } } +template +inline void RepeatedPtrFieldBase::CopyFrom(const RepeatedPtrFieldBase& other) { + if (&other == this) return; + RepeatedPtrFieldBase::Clear(); + RepeatedPtrFieldBase::MergeFrom(other); +} + inline int RepeatedPtrFieldBase::Capacity() const { return total_size_; } @@ -707,13 +966,14 @@ RepeatedPtrFieldBase::data() const { } inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) { - std::swap(elements_[index1], elements_[index2]); + using std::swap; // enable ADL with fallback + swap(elements_[index1], elements_[index2]); } template inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const { int allocated_bytes = - (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0; + (elements_ != NULL) ? total_size_ * sizeof(elements_[0]) : 0; for (int i = 0; i < allocated_size_; ++i) { allocated_bytes += TypeHandler::SpaceUsed(*cast(elements_[i])); } @@ -770,7 +1030,6 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseLast() { return result; } - inline int RepeatedPtrFieldBase::ClearedCount() const { return allocated_size_ - current_size_; } @@ -794,22 +1053,57 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() { template class RepeatedPtrField::TypeHandler - : public internal::GenericTypeHandler {}; + : public internal::GenericTypeHandler { +}; template <> class RepeatedPtrField::TypeHandler - : public internal::StringTypeHandler {}; + : public internal::StringTypeHandler { +}; template inline RepeatedPtrField::RepeatedPtrField() {} template +inline RepeatedPtrField::RepeatedPtrField( + const RepeatedPtrField& other) + : RepeatedPtrFieldBase() { + CopyFrom(other); +} + +template +template +inline RepeatedPtrField::RepeatedPtrField( + Iter begin, const Iter& end) { + int reserve = internal::CalculateReserve(begin, end); + if (reserve != -1) { + Reserve(reserve); + } + for (; begin != end; ++begin) { + *Add() = *begin; + } +} + +template RepeatedPtrField::~RepeatedPtrField() { Destroy(); } template +inline RepeatedPtrField& RepeatedPtrField::operator=( + const RepeatedPtrField& other) { + if (this != &other) + CopyFrom(other); + return *this; +} + +template +inline bool RepeatedPtrField::empty() const { + return RepeatedPtrFieldBase::empty(); +} + +template inline int RepeatedPtrField::size() const { return RepeatedPtrFieldBase::size(); } @@ -819,6 +1113,7 @@ inline const Element& RepeatedPtrField::Get(int index) const { return RepeatedPtrFieldBase::Get(index); } + template inline Element* RepeatedPtrField::Mutable(int index) { return RepeatedPtrFieldBase::Mutable(index); @@ -835,6 +1130,33 @@ inline void RepeatedPtrField::RemoveLast() { } template +inline void RepeatedPtrField::DeleteSubrange(int start, int num) { + GOOGLE_DCHECK_GE(start, 0); + GOOGLE_DCHECK_GE(num, 0); + GOOGLE_DCHECK_LE(start + num, size()); + for (int i = 0; i < num; ++i) + delete RepeatedPtrFieldBase::Mutable(start + i); + ExtractSubrange(start, num, NULL); +} + +template +inline void RepeatedPtrField::ExtractSubrange( + int start, int num, Element** elements) { + GOOGLE_DCHECK_GE(start, 0); + GOOGLE_DCHECK_GE(num, 0); + GOOGLE_DCHECK_LE(start + num, size()); + + if (num > 0) { + // Save the values of the removed elements if requested. + if (elements != NULL) { + for (int i = 0; i < num; ++i) + elements[i] = RepeatedPtrFieldBase::Mutable(i + start); + } + CloseGap(start, num); + } +} + +template inline void RepeatedPtrField::Clear() { RepeatedPtrFieldBase::Clear(); } @@ -846,6 +1168,12 @@ inline void RepeatedPtrField::MergeFrom( } template +inline void RepeatedPtrField::CopyFrom( + const RepeatedPtrField& other) { + RepeatedPtrFieldBase::CopyFrom(other); +} + +template inline Element** RepeatedPtrField::mutable_data() { return RepeatedPtrFieldBase::mutable_data(); } @@ -914,7 +1242,7 @@ namespace internal { // refer to this class directly; use RepeatedPtrField::iterator instead. // // The iterator for RepeatedPtrField, RepeatedPtrIterator, is -// very similar to iterator_ptr in util/gtl/iterator_adaptors-inl.h, +// very similar to iterator_ptr in util/gtl/iterator_adaptors.h, // but adds random-access operators and is modified to wrap a void** base // iterator (since RepeatedPtrField stores its array as a void* array and // casting void** to T** would violate C++ aliasing rules). @@ -930,6 +1258,10 @@ class RepeatedPtrIterator typedef std::iterator< std::random_access_iterator_tag, Element> superclass; + // Shadow the value_type in std::iterator<> because const_iterator::value_type + // needs to be T, not const T. + typedef typename remove_const::type value_type; + // Let the compiler know that these are type names, so we don't have to // write "typename" in front of them everywhere. typedef typename superclass::reference reference; @@ -944,7 +1276,7 @@ class RepeatedPtrIterator template RepeatedPtrIterator(const RepeatedPtrIterator& other) : it_(other.it_) { - // Force a compiler error if the other type is not convertable to ours. + // Force a compiler error if the other type is not convertible to ours. if (false) { implicit_cast(0); } @@ -1010,14 +1342,21 @@ class RepeatedPtrIterator // rather than the objects themselves as RepeatedPtrIterator does. // Consider using this when working with stl algorithms that change // the array. -template +// The VoidPtr template parameter holds the type-agnostic pointer value +// referenced by the iterator. It should either be "void *" for a mutable +// iterator, or "const void *" for a constant iterator. +template class RepeatedPtrOverPtrsIterator : public std::iterator { public: - typedef RepeatedPtrOverPtrsIterator iterator; + typedef RepeatedPtrOverPtrsIterator iterator; typedef std::iterator< std::random_access_iterator_tag, Element*> superclass; + // Shadow the value_type in std::iterator<> because const_iterator::value_type + // needs to be T, not const T. + typedef typename remove_const::type value_type; + // Let the compiler know that these are type names, so we don't have to // write "typename" in front of them everywhere. typedef typename superclass::reference reference; @@ -1025,7 +1364,7 @@ class RepeatedPtrOverPtrsIterator typedef typename superclass::difference_type difference_type; RepeatedPtrOverPtrsIterator() : it_(NULL) {} - explicit RepeatedPtrOverPtrsIterator(void** it) : it_(it) {} + explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {} // dereferenceable reference operator*() const { return *reinterpret_cast(it_); } @@ -1080,10 +1419,9 @@ class RepeatedPtrOverPtrsIterator friend class RepeatedPtrIterator; // The internal iterator. - void** it_; + VoidPtr* it_; }; - } // namespace internal template @@ -1113,10 +1451,21 @@ RepeatedPtrField::pointer_begin() { return pointer_iterator(raw_mutable_data()); } template +inline typename RepeatedPtrField::const_pointer_iterator +RepeatedPtrField::pointer_begin() const { + return const_pointer_iterator(const_cast(raw_mutable_data())); +} +template inline typename RepeatedPtrField::pointer_iterator RepeatedPtrField::pointer_end() { return pointer_iterator(raw_mutable_data() + size()); } +template +inline typename RepeatedPtrField::const_pointer_iterator +RepeatedPtrField::pointer_end() const { + return const_pointer_iterator( + const_cast(raw_mutable_data() + size())); +} // Iterators and helper functions that follow the spirit of the STL @@ -1126,7 +1475,7 @@ RepeatedPtrField::pointer_end() { // std::copy(some_sequence.begin(), some_sequence.end(), // google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence())); // -// Ported by johannes from util/gtl/proto-array-iterators-inl.h +// Ported by johannes from util/gtl/proto-array-iterators.h namespace internal { // A back inserter for RepeatedField objects. @@ -1147,12 +1496,12 @@ template class RepeatedFieldBackInsertIterator RepeatedFieldBackInsertIterator& operator++() { return *this; } - RepeatedFieldBackInsertIterator& operator++(int ignores_parameter) { + RepeatedFieldBackInsertIterator& operator++(int /* unused */) { return *this; } private: - RepeatedField* const field_; + RepeatedField* field_; }; // A back inserter for RepeatedPtrField objects. @@ -1178,12 +1527,12 @@ template class RepeatedPtrFieldBackInsertIterator RepeatedPtrFieldBackInsertIterator& operator++() { return *this; } - RepeatedPtrFieldBackInsertIterator& operator++(int ignores_parameter) { + RepeatedPtrFieldBackInsertIterator& operator++(int /* unused */) { return *this; } private: - RepeatedPtrField* const field_; + RepeatedPtrField* field_; }; // A back inserter for RepeatedPtrFields that inserts by transfering ownership @@ -1207,26 +1556,32 @@ template class AllocatedRepeatedPtrFieldBackInsertIterator return *this; } AllocatedRepeatedPtrFieldBackInsertIterator& operator++( - int ignores_parameter) { + int /* unused */) { return *this; } private: - RepeatedPtrField* const field_; + RepeatedPtrField* field_; }; } // namespace internal // Provides a back insert iterator for RepeatedField instances, -// similar to std::back_inserter(). Note the identically named -// function for RepeatedPtrField instances. +// similar to std::back_inserter(). template internal::RepeatedFieldBackInsertIterator RepeatedFieldBackInserter(RepeatedField* const mutable_field) { return internal::RepeatedFieldBackInsertIterator(mutable_field); } // Provides a back insert iterator for RepeatedPtrField instances, -// similar to std::back_inserter(). Note the identically named -// function for RepeatedField instances. +// similar to std::back_inserter(). +template internal::RepeatedPtrFieldBackInsertIterator +RepeatedPtrFieldBackInserter(RepeatedPtrField* const mutable_field) { + return internal::RepeatedPtrFieldBackInsertIterator(mutable_field); +} + +// Special back insert iterator for RepeatedPtrField instances, just in +// case someone wants to write generic template code that can access both +// RepeatedFields and RepeatedPtrFields using a common name. template internal::RepeatedPtrFieldBackInsertIterator RepeatedFieldBackInserter(RepeatedPtrField* const mutable_field) { return internal::RepeatedPtrFieldBackInsertIterator(mutable_field); diff --git a/src/google/protobuf/repeated_field_reflection_unittest.cc b/src/google/protobuf/repeated_field_reflection_unittest.cc new file mode 100644 index 0000000..a40162d --- /dev/null +++ b/src/google/protobuf/repeated_field_reflection_unittest.cc @@ -0,0 +1,195 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: tgs@google.com (Tom Szymanski) +// +// Test reflection methods for aggregate access to Repeated[Ptr]Fields. +// This test proto2 methods on a proto2 layout. + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +using unittest::ForeignMessage; +using unittest::TestAllTypes; +using unittest::TestAllExtensions; + +namespace { + +static int Func(int i, int j) { + return i * j; +} + +static string StrFunc(int i, int j) { + string str; + SStringPrintf(&str, "%d", Func(i, 4)); + return str; +} + + +TEST(RepeatedFieldReflectionTest, RegularFields) { + TestAllTypes message; + const Reflection* refl = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + for (int i = 0; i < 10; ++i) { + message.add_repeated_int32(Func(i, 1)); + message.add_repeated_double(Func(i, 2)); + message.add_repeated_string(StrFunc(i, 5)); + message.add_repeated_foreign_message()->set_c(Func(i, 6)); + } + + // Get FieldDescriptors for all the fields of interest. + const FieldDescriptor* fd_repeated_int32 = + desc->FindFieldByName("repeated_int32"); + const FieldDescriptor* fd_repeated_double = + desc->FindFieldByName("repeated_double"); + const FieldDescriptor* fd_repeated_string = + desc->FindFieldByName("repeated_string"); + const FieldDescriptor* fd_repeated_foreign_message = + desc->FindFieldByName("repeated_foreign_message"); + + // Get RepeatedField objects for all fields of interest. + const RepeatedField& rf_int32 = + refl->GetRepeatedField(message, fd_repeated_int32); + const RepeatedField& rf_double = + refl->GetRepeatedField(message, fd_repeated_double); + + // Get mutable RepeatedField objects for all fields of interest. + RepeatedField* mrf_int32 = + refl->MutableRepeatedField(&message, fd_repeated_int32); + RepeatedField* mrf_double = + refl->MutableRepeatedField(&message, fd_repeated_double); + + // Get RepeatedPtrField objects for all fields of interest. + const RepeatedPtrField& rpf_string = + refl->GetRepeatedPtrField(message, fd_repeated_string); + const RepeatedPtrField& rpf_foreign_message = + refl->GetRepeatedPtrField( + message, fd_repeated_foreign_message); + const RepeatedPtrField& rpf_message = + refl->GetRepeatedPtrField( + message, fd_repeated_foreign_message); + + // Get mutable RepeatedPtrField objects for all fields of interest. + RepeatedPtrField* mrpf_string = + refl->MutableRepeatedPtrField(&message, fd_repeated_string); + RepeatedPtrField* mrpf_foreign_message = + refl->MutableRepeatedPtrField( + &message, fd_repeated_foreign_message); + RepeatedPtrField* mrpf_message = + refl->MutableRepeatedPtrField( + &message, fd_repeated_foreign_message); + + // Make sure we can do get and sets through the Repeated[Ptr]Field objects. + for (int i = 0; i < 10; ++i) { + // Check gets through const objects. + EXPECT_EQ(rf_int32.Get(i), Func(i, 1)); + EXPECT_EQ(rf_double.Get(i), Func(i, 2)); + EXPECT_EQ(rpf_string.Get(i), StrFunc(i, 5)); + EXPECT_EQ(rpf_foreign_message.Get(i).c(), Func(i, 6)); + EXPECT_EQ(down_cast(&rpf_message.Get(i))->c(), + Func(i, 6)); + + // Check gets through mutable objects. + EXPECT_EQ(mrf_int32->Get(i), Func(i, 1)); + EXPECT_EQ(mrf_double->Get(i), Func(i, 2)); + EXPECT_EQ(mrpf_string->Get(i), StrFunc(i, 5)); + EXPECT_EQ(mrpf_foreign_message->Get(i).c(), Func(i, 6)); + EXPECT_EQ(down_cast(&mrpf_message->Get(i))->c(), + Func(i, 6)); + + // Check sets through mutable objects. + mrf_int32->Set(i, Func(i, -1)); + mrf_double->Set(i, Func(i, -2)); + mrpf_string->Mutable(i)->assign(StrFunc(i, -5)); + mrpf_foreign_message->Mutable(i)->set_c(Func(i, -6)); + EXPECT_EQ(message.repeated_int32(i), Func(i, -1)); + EXPECT_EQ(message.repeated_double(i), Func(i, -2)); + EXPECT_EQ(message.repeated_string(i), StrFunc(i, -5)); + EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, -6)); + down_cast(mrpf_message->Mutable(i))->set_c(Func(i, 7)); + EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, 7)); + } + +#ifdef PROTOBUF_HAS_DEATH_TEST + // Make sure types are checked correctly at runtime. + const FieldDescriptor* fd_optional_int32 = + desc->FindFieldByName("optional_int32"); + EXPECT_DEATH(refl->GetRepeatedField( + message, fd_optional_int32), "requires a repeated field"); + EXPECT_DEATH(refl->GetRepeatedField( + message, fd_repeated_int32), "not the right type"); + EXPECT_DEATH(refl->GetRepeatedPtrField( + message, fd_repeated_foreign_message), "wrong submessage type"); +#endif // PROTOBUF_HAS_DEATH_TEST +} + + + + +TEST(RepeatedFieldReflectionTest, ExtensionFields) { + TestAllExtensions extended_message; + const Reflection* refl = extended_message.GetReflection(); + const Descriptor* desc = extended_message.GetDescriptor(); + + for (int i = 0; i < 10; ++i) { + extended_message.AddExtension( + unittest::repeated_int64_extension, Func(i, 1)); + } + + const FieldDescriptor* fd_repeated_int64_extension = + desc->file()->FindExtensionByName("repeated_int64_extension"); + GOOGLE_CHECK(fd_repeated_int64_extension != NULL); + + const RepeatedField& rf_int64_extension = + refl->GetRepeatedField(extended_message, + fd_repeated_int64_extension); + + RepeatedField* mrf_int64_extension = + refl->MutableRepeatedField(&extended_message, + fd_repeated_int64_extension); + + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(Func(i, 1), rf_int64_extension.Get(i)); + mrf_int64_extension->Set(i, Func(i, -1)); + EXPECT_EQ(Func(i, -1), + extended_message.GetExtension(unittest::repeated_int64_extension, i)); + } +} + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index 7c35f60..334fdfc 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -36,6 +36,7 @@ // other proto2 unittests. #include +#include #include #include @@ -46,7 +47,7 @@ #include #include #include -#include +#include namespace google { using protobuf_unittest::TestAllTypes; @@ -54,42 +55,48 @@ using protobuf_unittest::TestAllTypes; namespace protobuf { namespace { -// Test operations on a RepeatedField which is small enough that it does -// not allocate a separate array for storage. +// Test operations on a small RepeatedField. TEST(RepeatedField, Small) { RepeatedField field; + EXPECT_TRUE(field.empty()); EXPECT_EQ(field.size(), 0); field.Add(5); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 1); EXPECT_EQ(field.Get(0), 5); field.Add(42); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 2); EXPECT_EQ(field.Get(0), 5); EXPECT_EQ(field.Get(1), 42); field.Set(1, 23); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 2); EXPECT_EQ(field.Get(0), 5); EXPECT_EQ(field.Get(1), 23); - EXPECT_EQ(field.SpaceUsedExcludingSelf(), 0); field.RemoveLast(); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 1); EXPECT_EQ(field.Get(0), 5); field.Clear(); + EXPECT_TRUE(field.empty()); EXPECT_EQ(field.size(), 0); - EXPECT_EQ(field.SpaceUsedExcludingSelf(), 0); + int expected_usage = 4 * sizeof(int); + EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage); } + // Test operations on a RepeatedField which is large enough to allocate a // separate array. TEST(RepeatedField, Large) { @@ -99,6 +106,7 @@ TEST(RepeatedField, Large) { field.Add(i * i); } + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 16); for (int i = 0; i < 16; i++) { @@ -117,9 +125,20 @@ TEST(RepeatedField, SwapSmallSmall) { field1.Add(5); field1.Add(42); + EXPECT_FALSE(field1.empty()); + EXPECT_EQ(field1.size(), 2); + EXPECT_EQ(field1.Get(0), 5); + EXPECT_EQ(field1.Get(1), 42); + + EXPECT_TRUE(field2.empty()); + EXPECT_EQ(field2.size(), 0); + field1.Swap(&field2); + EXPECT_TRUE(field1.empty()); EXPECT_EQ(field1.size(), 0); + + EXPECT_FALSE(field2.empty()); EXPECT_EQ(field2.size(), 2); EXPECT_EQ(field2.Get(0), 5); EXPECT_EQ(field2.Get(1), 42); @@ -211,12 +230,26 @@ TEST(RepeatedField, ReserveLessThanExisting) { EXPECT_EQ(20, ReservedSpace(&field)); } +TEST(RepeatedField, Resize) { + RepeatedField field; + field.Resize(2, 1); + EXPECT_EQ(2, field.size()); + field.Resize(5, 2); + EXPECT_EQ(5, field.size()); + field.Resize(4, 3); + ASSERT_EQ(4, field.size()); + EXPECT_EQ(1, field.Get(0)); + EXPECT_EQ(1, field.Get(1)); + EXPECT_EQ(2, field.Get(2)); + EXPECT_EQ(2, field.Get(3)); + field.Resize(0, 4); + EXPECT_TRUE(field.empty()); +} + TEST(RepeatedField, MergeFrom) { RepeatedField source, destination; - source.Add(4); source.Add(5); - destination.Add(1); destination.Add(2); destination.Add(3); @@ -224,7 +257,6 @@ TEST(RepeatedField, MergeFrom) { destination.MergeFrom(source); ASSERT_EQ(5, destination.size()); - EXPECT_EQ(1, destination.Get(0)); EXPECT_EQ(2, destination.Get(1)); EXPECT_EQ(3, destination.Get(2)); @@ -232,6 +264,94 @@ TEST(RepeatedField, MergeFrom) { EXPECT_EQ(5, destination.Get(4)); } +#ifdef PROTOBUF_HAS_DEATH_TEST +TEST(RepeatedField, MergeFromSelf) { + RepeatedField me; + me.Add(3); + EXPECT_DEATH(me.MergeFrom(me), ""); +} +#endif // PROTOBUF_HAS_DEATH_TEST + +TEST(RepeatedField, CopyFrom) { + RepeatedField source, destination; + source.Add(4); + source.Add(5); + destination.Add(1); + destination.Add(2); + destination.Add(3); + + destination.CopyFrom(source); + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ(4, destination.Get(0)); + EXPECT_EQ(5, destination.Get(1)); +} + +TEST(RepeatedField, CopyFromSelf) { + RepeatedField me; + me.Add(3); + me.CopyFrom(me); + ASSERT_EQ(1, me.size()); + EXPECT_EQ(3, me.Get(0)); +} + +TEST(RepeatedField, CopyConstruct) { + RepeatedField source; + source.Add(1); + source.Add(2); + + RepeatedField destination(source); + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ(1, destination.Get(0)); + EXPECT_EQ(2, destination.Get(1)); +} + +TEST(RepeatedField, IteratorConstruct) { + vector values; + values.push_back(1); + values.push_back(2); + + RepeatedField field(values.begin(), values.end()); + ASSERT_EQ(values.size(), field.size()); + EXPECT_EQ(values[0], field.Get(0)); + EXPECT_EQ(values[1], field.Get(1)); + + RepeatedField other(field.begin(), field.end()); + ASSERT_EQ(values.size(), other.size()); + EXPECT_EQ(values[0], other.Get(0)); + EXPECT_EQ(values[1], other.Get(1)); +} + +TEST(RepeatedField, CopyAssign) { + RepeatedField source, destination; + source.Add(4); + source.Add(5); + destination.Add(1); + destination.Add(2); + destination.Add(3); + + destination = source; + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ(4, destination.Get(0)); + EXPECT_EQ(5, destination.Get(1)); +} + +TEST(RepeatedField, SelfAssign) { + // Verify that assignment to self does not destroy data. + RepeatedField source, *p; + p = &source; + source.Add(7); + source.Add(8); + + *p = source; + + ASSERT_EQ(2, source.size()); + EXPECT_EQ(7, source.Get(0)); + EXPECT_EQ(8, source.Get(1)); +} + TEST(RepeatedField, MutableDataIsMutable) { RepeatedField field; field.Add(1); @@ -261,12 +381,47 @@ TEST(RepeatedField, Truncate) { // Truncations that don't change the size are allowed, but growing is not // allowed. field.Truncate(field.size()); -#ifdef GTEST_HAS_DEATH_TEST +#ifdef PROTOBUF_HAS_DEATH_TEST EXPECT_DEBUG_DEATH(field.Truncate(field.size() + 1), "new_size"); #endif } +TEST(RepeatedField, ExtractSubrange) { + // Exhaustively test every subrange in arrays of all sizes from 0 through 9. + for (int sz = 0; sz < 10; ++sz) { + for (int num = 0; num <= sz; ++num) { + for (int start = 0; start < sz - num; ++start) { + // Create RepeatedField with sz elements having values 0 through sz-1. + RepeatedField field; + for (int i = 0; i < sz; ++i) + field.Add(i); + EXPECT_EQ(field.size(), sz); + + // Create a catcher array and call ExtractSubrange. + int32 catcher[10]; + for (int i = 0; i < 10; ++i) + catcher[i] = -1; + field.ExtractSubrange(start, num, catcher); + + // Does the resulting array have the right size? + EXPECT_EQ(field.size(), sz - num); + + // Were the removed elements extracted into the catcher array? + for (int i = 0; i < num; ++i) + EXPECT_EQ(catcher[i], start + i); + EXPECT_EQ(catcher[num], -1); + + // Does the resulting array contain the right values? + for (int i = 0; i < start; ++i) + EXPECT_EQ(field.Get(i), i); + for (int i = start; i < field.size(); ++i) + EXPECT_EQ(field.Get(i), i + num); + } + } + } +} + // =================================================================== // RepeatedPtrField tests. These pretty much just mirror the RepeatedField // tests above. @@ -274,32 +429,38 @@ TEST(RepeatedField, Truncate) { TEST(RepeatedPtrField, Small) { RepeatedPtrField field; + EXPECT_TRUE(field.empty()); EXPECT_EQ(field.size(), 0); field.Add()->assign("foo"); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 1); EXPECT_EQ(field.Get(0), "foo"); field.Add()->assign("bar"); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 2); EXPECT_EQ(field.Get(0), "foo"); EXPECT_EQ(field.Get(1), "bar"); field.Mutable(1)->assign("baz"); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 2); EXPECT_EQ(field.Get(0), "foo"); EXPECT_EQ(field.Get(1), "baz"); field.RemoveLast(); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 1); EXPECT_EQ(field.Get(0), "foo"); field.Clear(); + EXPECT_TRUE(field.empty()); EXPECT_EQ(field.size(), 0); } @@ -325,11 +486,27 @@ TEST(RepeatedPtrField, SwapSmallSmall) { RepeatedPtrField field1; RepeatedPtrField field2; + EXPECT_TRUE(field1.empty()); + EXPECT_EQ(field1.size(), 0); + EXPECT_TRUE(field2.empty()); + EXPECT_EQ(field2.size(), 0); + field1.Add()->assign("foo"); field1.Add()->assign("bar"); + + EXPECT_FALSE(field1.empty()); + EXPECT_EQ(field1.size(), 2); + EXPECT_EQ(field1.Get(0), "foo"); + EXPECT_EQ(field1.Get(1), "bar"); + + EXPECT_TRUE(field2.empty()); + EXPECT_EQ(field2.size(), 0); + field1.Swap(&field2); + EXPECT_TRUE(field1.empty()); EXPECT_EQ(field1.size(), 0); + EXPECT_EQ(field2.size(), 2); EXPECT_EQ(field2.Get(0), "foo"); EXPECT_EQ(field2.Get(1), "bar"); @@ -517,10 +694,8 @@ TEST(RepeatedPtrField, AddAlocated) { TEST(RepeatedPtrField, MergeFrom) { RepeatedPtrField source, destination; - source.Add()->assign("4"); source.Add()->assign("5"); - destination.Add()->assign("1"); destination.Add()->assign("2"); destination.Add()->assign("3"); @@ -528,7 +703,6 @@ TEST(RepeatedPtrField, MergeFrom) { destination.MergeFrom(source); ASSERT_EQ(5, destination.size()); - EXPECT_EQ("1", destination.Get(0)); EXPECT_EQ("2", destination.Get(1)); EXPECT_EQ("3", destination.Get(2)); @@ -536,6 +710,113 @@ TEST(RepeatedPtrField, MergeFrom) { EXPECT_EQ("5", destination.Get(4)); } +#ifdef PROTOBUF_HAS_DEATH_TEST +TEST(RepeatedPtrField, MergeFromSelf) { + RepeatedPtrField me; + me.Add()->assign("1"); + EXPECT_DEATH(me.MergeFrom(me), ""); +} +#endif // PROTOBUF_HAS_DEATH_TEST + +TEST(RepeatedPtrField, CopyFrom) { + RepeatedPtrField source, destination; + source.Add()->assign("4"); + source.Add()->assign("5"); + destination.Add()->assign("1"); + destination.Add()->assign("2"); + destination.Add()->assign("3"); + + destination.CopyFrom(source); + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ("4", destination.Get(0)); + EXPECT_EQ("5", destination.Get(1)); +} + +TEST(RepeatedPtrField, CopyFromSelf) { + RepeatedPtrField me; + me.Add()->assign("1"); + me.CopyFrom(me); + ASSERT_EQ(1, me.size()); + EXPECT_EQ("1", me.Get(0)); +} + +TEST(RepeatedPtrField, CopyConstruct) { + RepeatedPtrField source; + source.Add()->assign("1"); + source.Add()->assign("2"); + + RepeatedPtrField destination(source); + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ("1", destination.Get(0)); + EXPECT_EQ("2", destination.Get(1)); +} + +TEST(RepeatedPtrField, IteratorConstruct_String) { + vector values; + values.push_back("1"); + values.push_back("2"); + + RepeatedPtrField field(values.begin(), values.end()); + ASSERT_EQ(values.size(), field.size()); + EXPECT_EQ(values[0], field.Get(0)); + EXPECT_EQ(values[1], field.Get(1)); + + RepeatedPtrField other(field.begin(), field.end()); + ASSERT_EQ(values.size(), other.size()); + EXPECT_EQ(values[0], other.Get(0)); + EXPECT_EQ(values[1], other.Get(1)); +} + +TEST(RepeatedPtrField, IteratorConstruct_Proto) { + typedef TestAllTypes::NestedMessage Nested; + vector values; + values.push_back(Nested()); + values.back().set_bb(1); + values.push_back(Nested()); + values.back().set_bb(2); + + RepeatedPtrField field(values.begin(), values.end()); + ASSERT_EQ(values.size(), field.size()); + EXPECT_EQ(values[0].bb(), field.Get(0).bb()); + EXPECT_EQ(values[1].bb(), field.Get(1).bb()); + + RepeatedPtrField other(field.begin(), field.end()); + ASSERT_EQ(values.size(), other.size()); + EXPECT_EQ(values[0].bb(), other.Get(0).bb()); + EXPECT_EQ(values[1].bb(), other.Get(1).bb()); +} + +TEST(RepeatedPtrField, CopyAssign) { + RepeatedPtrField source, destination; + source.Add()->assign("4"); + source.Add()->assign("5"); + destination.Add()->assign("1"); + destination.Add()->assign("2"); + destination.Add()->assign("3"); + + destination = source; + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ("4", destination.Get(0)); + EXPECT_EQ("5", destination.Get(1)); +} + +TEST(RepeatedPtrField, SelfAssign) { + // Verify that assignment to self does not destroy data. + RepeatedPtrField source, *p; + p = &source; + source.Add()->assign("7"); + source.Add()->assign("8"); + + *p = source; + + ASSERT_EQ(2, source.size()); + EXPECT_EQ("7", source.Get(0)); + EXPECT_EQ("8", source.Get(1)); +} + TEST(RepeatedPtrField, MutableDataIsMutable) { RepeatedPtrField field; *field.Add() = "1"; @@ -547,6 +828,77 @@ TEST(RepeatedPtrField, MutableDataIsMutable) { EXPECT_EQ("2", field.Get(0)); } +TEST(RepeatedPtrField, ExtractSubrange) { + // Exhaustively test every subrange in arrays of all sizes from 0 through 9 + // with 0 through 3 cleared elements at the end. + for (int sz = 0; sz < 10; ++sz) { + for (int num = 0; num <= sz; ++num) { + for (int start = 0; start < sz - num; ++start) { + for (int extra = 0; extra < 4; ++extra) { + vector subject; + + // Create an array with "sz" elements and "extra" cleared elements. + RepeatedPtrField field; + for (int i = 0; i < sz + extra; ++i) { + subject.push_back(new string()); + field.AddAllocated(subject[i]); + } + EXPECT_EQ(field.size(), sz + extra); + for (int i = 0; i < extra; ++i) + field.RemoveLast(); + EXPECT_EQ(field.size(), sz); + EXPECT_EQ(field.ClearedCount(), extra); + + // Create a catcher array and call ExtractSubrange. + string* catcher[10]; + for (int i = 0; i < 10; ++i) + catcher[i] = NULL; + field.ExtractSubrange(start, num, catcher); + + // Does the resulting array have the right size? + EXPECT_EQ(field.size(), sz - num); + + // Were the removed elements extracted into the catcher array? + for (int i = 0; i < num; ++i) + EXPECT_EQ(catcher[i], subject[start + i]); + EXPECT_EQ(NULL, catcher[num]); + + // Does the resulting array contain the right values? + for (int i = 0; i < start; ++i) + EXPECT_EQ(field.Mutable(i), subject[i]); + for (int i = start; i < field.size(); ++i) + EXPECT_EQ(field.Mutable(i), subject[i + num]); + + // Reinstate the cleared elements. + EXPECT_EQ(field.ClearedCount(), extra); + for (int i = 0; i < extra; ++i) + field.Add(); + EXPECT_EQ(field.ClearedCount(), 0); + EXPECT_EQ(field.size(), sz - num + extra); + + // Make sure the extra elements are all there (in some order). + for (int i = sz; i < sz + extra; ++i) { + int count = 0; + for (int j = sz; j < sz + extra; ++j) { + if (field.Mutable(j - num) == subject[i]) + count += 1; + } + EXPECT_EQ(count, 1); + } + + // Release the caught elements. + for (int i = 0; i < num; ++i) + delete catcher[i]; + } + } + } + } +} + +TEST(RepeatedPtrField, DeleteSubrange) { + // DeleteSubrange is a trivial extension of ExtendSubrange. +} + // =================================================================== // Iterator tests stolen from net/proto/proto-array_unittest. @@ -564,7 +916,8 @@ class RepeatedFieldIteratorTest : public testing::Test { TEST_F(RepeatedFieldIteratorTest, Convertible) { RepeatedField::iterator iter = proto_array_.begin(); RepeatedField::const_iterator c_iter = iter; - EXPECT_EQ(0, *c_iter); + RepeatedField::value_type value = *c_iter; + EXPECT_EQ(0, value); } TEST_F(RepeatedFieldIteratorTest, MutableIteration) { @@ -613,6 +966,8 @@ class RepeatedPtrFieldIteratorTest : public testing::Test { TEST_F(RepeatedPtrFieldIteratorTest, Convertible) { RepeatedPtrField::iterator iter = proto_array_.begin(); RepeatedPtrField::const_iterator c_iter = iter; + RepeatedPtrField::value_type value = *c_iter; + EXPECT_EQ("foo", value); } TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) { @@ -638,6 +993,30 @@ TEST_F(RepeatedPtrFieldIteratorTest, ConstIteration) { EXPECT_EQ("baz", *(--const_proto_array.end())); } +TEST_F(RepeatedPtrFieldIteratorTest, MutableReverseIteration) { + RepeatedPtrField::reverse_iterator iter = proto_array_.rbegin(); + EXPECT_EQ("baz", *iter); + ++iter; + EXPECT_EQ("bar", *(iter++)); + EXPECT_EQ("foo", *iter); + ++iter; + EXPECT_TRUE(proto_array_.rend() == iter); + EXPECT_EQ("foo", *(--proto_array_.rend())); +} + +TEST_F(RepeatedPtrFieldIteratorTest, ConstReverseIteration) { + const RepeatedPtrField& const_proto_array = proto_array_; + RepeatedPtrField::const_reverse_iterator iter + = const_proto_array.rbegin(); + EXPECT_EQ("baz", *iter); + ++iter; + EXPECT_EQ("bar", *(iter++)); + EXPECT_EQ("foo", *iter); + ++iter; + EXPECT_TRUE(const_proto_array.rend() == iter); + EXPECT_EQ("foo", *(--const_proto_array.rend())); +} + TEST_F(RepeatedPtrFieldIteratorTest, RandomAccess) { RepeatedPtrField::iterator iter = proto_array_.begin(); RepeatedPtrField::iterator iter2 = iter; @@ -705,14 +1084,23 @@ class RepeatedPtrFieldPtrsIteratorTest : public testing::Test { proto_array_.Add()->assign("foo"); proto_array_.Add()->assign("bar"); proto_array_.Add()->assign("baz"); + const_proto_array_ = &proto_array_; } RepeatedPtrField proto_array_; + const RepeatedPtrField* const_proto_array_; }; TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) { RepeatedPtrField::pointer_iterator iter = proto_array_.pointer_begin(); + static_cast(iter); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertibleConstPtr) { + RepeatedPtrField::const_pointer_iterator iter = + const_proto_array_->pointer_begin(); + static_cast(iter); } TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) { @@ -727,6 +1115,18 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) { EXPECT_EQ("baz", **(--proto_array_.pointer_end())); } +TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutableConstPtrIteration) { + RepeatedPtrField::const_pointer_iterator iter = + const_proto_array_->pointer_begin(); + EXPECT_EQ("foo", **iter); + ++iter; + EXPECT_EQ("bar", **(iter++)); + EXPECT_EQ("baz", **iter); + ++iter; + EXPECT_TRUE(const_proto_array_->pointer_end() == iter); + EXPECT_EQ("baz", **(--const_proto_array_->pointer_end())); +} + TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) { RepeatedPtrField::pointer_iterator iter = proto_array_.pointer_begin(); @@ -740,6 +1140,19 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) { EXPECT_EQ(3, proto_array_.end() - proto_array_.begin()); } +TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomConstPtrAccess) { + RepeatedPtrField::const_pointer_iterator iter = + const_proto_array_->pointer_begin(); + RepeatedPtrField::const_pointer_iterator iter2 = iter; + ++iter2; + ++iter2; + EXPECT_TRUE(iter + 2 == iter2); + EXPECT_TRUE(iter == iter2 - 2); + EXPECT_EQ("baz", *iter[2]); + EXPECT_EQ("baz", **(iter + 2)); + EXPECT_EQ(3, const_proto_array_->end() - const_proto_array_->begin()); +} + TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) { RepeatedPtrField::pointer_iterator iter = proto_array_.pointer_begin(); @@ -754,6 +1167,20 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) { EXPECT_TRUE(iter >= iter); } +TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstPtr) { + RepeatedPtrField::const_pointer_iterator iter = + const_proto_array_->pointer_begin(); + RepeatedPtrField::const_pointer_iterator iter2 = iter + 1; + EXPECT_TRUE(iter == iter); + EXPECT_TRUE(iter != iter2); + EXPECT_TRUE(iter < iter2); + EXPECT_TRUE(iter <= iter2); + EXPECT_TRUE(iter <= iter); + EXPECT_TRUE(iter2 > iter); + EXPECT_TRUE(iter2 >= iter); + EXPECT_TRUE(iter >= iter); +} + // Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs. // Dereferencing an uninitialized iterator crashes the process. TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) { @@ -765,6 +1192,14 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) { EXPECT_TRUE(iter != proto_array_.pointer_end()); } +TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedConstPtrIterator) { + RepeatedPtrField::const_pointer_iterator iter; + EXPECT_TRUE(iter != const_proto_array_->pointer_begin()); + EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 1); + EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 2); + EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 3); + EXPECT_TRUE(iter != const_proto_array_->pointer_end()); +} // This comparison functor is required by the tests for RepeatedPtrOverPtrs. // They operate on strings and need to compare strings as strings in @@ -774,9 +1209,7 @@ struct StringLessThan { bool operator()(const string* z, const string& y) { return *z < y; } - bool operator()(const string* z, const string* y) { - return *z < *y; - } + bool operator()(const string* z, const string* y) const { return *z < *y; } }; TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { @@ -789,17 +1222,29 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { proto_array_.Add()->assign("x"); proto_array_.Add()->assign("y"); - RepeatedPtrField::pointer_iterator iter = - proto_array_.pointer_begin(); - string v = "f"; - RepeatedPtrField::pointer_iterator it = - lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(), - &v, StringLessThan()); + { + string v = "f"; + RepeatedPtrField::pointer_iterator it = + lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(), + &v, StringLessThan()); + + GOOGLE_CHECK(*it != NULL); + + EXPECT_EQ(**it, "n"); + EXPECT_TRUE(it == proto_array_.pointer_begin() + 3); + } + { + string v = "f"; + RepeatedPtrField::const_pointer_iterator it = + lower_bound(const_proto_array_->pointer_begin(), + const_proto_array_->pointer_end(), + &v, StringLessThan()); - GOOGLE_CHECK(*it != NULL); + GOOGLE_CHECK(*it != NULL); - EXPECT_EQ(**it, "n"); - EXPECT_TRUE(it == proto_array_.pointer_begin() + 3); + EXPECT_EQ(**it, "n"); + EXPECT_TRUE(it == const_proto_array_->pointer_begin() + 3); + } } TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) { @@ -925,13 +1370,24 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, Halves) { TEST_F(RepeatedFieldInsertionIteratorsTest, Words) { ASSERT_EQ(words.size(), protobuffer.repeated_string_size()); - EXPECT_EQ(words.at(0), protobuffer.repeated_string(0)); - EXPECT_EQ(words.at(1), protobuffer.repeated_string(1)); - EXPECT_EQ(words.at(2), protobuffer.repeated_string(2)); - EXPECT_EQ(words.at(3), protobuffer.repeated_string(3)); - EXPECT_EQ(words.at(4), protobuffer.repeated_string(4)); - EXPECT_EQ(words.at(5), protobuffer.repeated_string(5)); - EXPECT_EQ(words.at(6), protobuffer.repeated_string(6)); + for (int i = 0; i < words.size(); ++i) + EXPECT_EQ(words.at(i), protobuffer.repeated_string(i)); +} + +TEST_F(RepeatedFieldInsertionIteratorsTest, Words2) { + words.clear(); + words.push_back("sing"); + words.push_back("a"); + words.push_back("song"); + words.push_back("of"); + words.push_back("six"); + words.push_back("pence"); + protobuffer.mutable_repeated_string()->Clear(); + std::copy(words.begin(), words.end(), RepeatedPtrFieldBackInserter( + protobuffer.mutable_repeated_string())); + ASSERT_EQ(words.size(), protobuffer.repeated_string_size()); + for (int i = 0; i < words.size(); ++i) + EXPECT_EQ(words.at(i), protobuffer.repeated_string(i)); } TEST_F(RepeatedFieldInsertionIteratorsTest, Nesteds) { diff --git a/src/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h new file mode 100644 index 0000000..76c026c --- /dev/null +++ b/src/google/protobuf/stubs/atomicops.h @@ -0,0 +1,216 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// The routines exported by this module are subtle. If you use them, even if +// you get the code right, it will depend on careful reasoning about atomicity +// and memory ordering; it will be less readable, and harder to maintain. If +// you plan to use these routines, you should have a good reason, such as solid +// evidence that performance would otherwise suffer, or there being no +// alternative. You should assume only properties explicitly guaranteed by the +// specifications in this file. You are almost certainly _not_ writing code +// just for the x86; if you assume x86 semantics, x86 hardware bugs and +// implementations on other archtectures will cause your code to break. If you +// do not know what you are doing, avoid these routines, and use a Mutex. +// +// It is incorrect to make direct assignments to/from an atomic variable. +// You should use one of the Load or Store routines. The NoBarrier +// versions are provided when no barriers are needed: +// NoBarrier_Store() +// NoBarrier_Load() +// Although there are currently no compiler enforcement, you are encouraged +// to use these. + +// This header and the implementations for each platform (located in +// atomicops_internals_*) must be kept in sync with the upstream code (V8). + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_H_ + +// Don't include this file for people not concerned about thread safety. +#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY + +#include + +namespace google { +namespace protobuf { +namespace internal { + +typedef int32 Atomic32; +#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT +// We need to be able to go between Atomic64 and AtomicWord implicitly. This +// means Atomic64 and AtomicWord should be the same type on 64-bit. +#if defined(__ILP32__) || defined(GOOGLE_PROTOBUF_OS_NACL) +// NaCl's intptr_t is not actually 64-bits on 64-bit! +// http://code.google.com/p/nativeclient/issues/detail?id=1162 +typedef int64 Atomic64; +#else +typedef intptr_t Atomic64; +#endif +#endif + +// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or +// Atomic64 routines below, depending on your architecture. +typedef intptr_t AtomicWord; + +// Atomically execute: +// result = *ptr; +// if (*ptr == old_value) +// *ptr = new_value; +// return result; +// +// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". +// Always return the old value of "*ptr" +// +// This routine implies no memory barriers. +Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value); + +// Atomically store new_value into *ptr, returning the previous value held in +// *ptr. This routine implies no memory barriers. +Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); + +// Atomically increment *ptr by "increment". Returns the new value of +// *ptr with the increment applied. This routine implies no memory barriers. +Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment); + +Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment); + +// These following lower-level operations are typically useful only to people +// implementing higher-level synchronization operations like spinlocks, +// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or +// a store with appropriate memory-ordering instructions. "Acquire" operations +// ensure that no later memory access can be reordered ahead of the operation. +// "Release" operations ensure that no previous memory access can be reordered +// after the operation. "Barrier" operations have both "Acquire" and "Release" +// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory +// access. +Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value); +Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value); + +#if defined(__MINGW32__) && defined(MemoryBarrier) +#undef MemoryBarrier +#endif +void MemoryBarrier(); +void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value); +void Acquire_Store(volatile Atomic32* ptr, Atomic32 value); +void Release_Store(volatile Atomic32* ptr, Atomic32 value); + +Atomic32 NoBarrier_Load(volatile const Atomic32* ptr); +Atomic32 Acquire_Load(volatile const Atomic32* ptr); +Atomic32 Release_Load(volatile const Atomic32* ptr); + +// 64-bit atomic operations (only available on 64-bit processors). +#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT +Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value); +Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); +Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); +Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); + +Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value); +Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value); +void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value); +void Acquire_Store(volatile Atomic64* ptr, Atomic64 value); +void Release_Store(volatile Atomic64* ptr, Atomic64 value); +Atomic64 NoBarrier_Load(volatile const Atomic64* ptr); +Atomic64 Acquire_Load(volatile const Atomic64* ptr); +Atomic64 Release_Load(volatile const Atomic64* ptr); +#endif // GOOGLE_PROTOBUF_ARCH_64_BIT + +} // namespace internal +} // namespace protobuf +} // namespace google + +// Include our platform specific implementation. +#define GOOGLE_PROTOBUF_ATOMICOPS_ERROR \ +#error "Atomic operations are not supported on your platform" + +// ThreadSanitizer, http://clang.llvm.org/docs/ThreadSanitizer.html. +#if defined(THREAD_SANITIZER) +#include +// MSVC. +#elif defined(_MSC_VER) +#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64) +#include +#else +GOOGLE_PROTOBUF_ATOMICOPS_ERROR +#endif + +// Apple. +#elif defined(GOOGLE_PROTOBUF_OS_APPLE) +#include + +// GCC. +#elif defined(__GNUC__) +#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64) +#include +#elif defined(GOOGLE_PROTOBUF_ARCH_ARM) && defined(__linux__) +#include +#elif defined(GOOGLE_PROTOBUF_ARCH_AARCH64) +#include +#elif defined(GOOGLE_PROTOBUF_ARCH_ARM_QNX) +#include +#elif defined(GOOGLE_PROTOBUF_ARCH_MIPS) || defined(GOOGLE_PROTOBUF_ARCH_MIPS64) +#include +#elif defined(__native_client__) +#include +#elif (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)) +#include +#else +GOOGLE_PROTOBUF_ATOMICOPS_ERROR +#endif + +// Unknown. +#else +GOOGLE_PROTOBUF_ATOMICOPS_ERROR +#endif + +// On some platforms we need additional declarations to make AtomicWord +// compatible with our other Atomic* types. +#if defined(GOOGLE_PROTOBUF_OS_APPLE) +#include +#endif + +#undef GOOGLE_PROTOBUF_ATOMICOPS_ERROR + +#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h b/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h new file mode 100644 index 0000000..fe9727a --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h @@ -0,0 +1,325 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 file is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_ + +namespace google { +namespace protobuf { +namespace internal { + +inline void MemoryBarrier() { + __asm__ __volatile__ ("dmb ish" ::: "memory"); // NOLINT +} + +// NoBarrier versions of the operation include "memory" in the clobber list. +// This is not required for direct usage of the NoBarrier versions of the +// operations. However this is required for correctness when they are used as +// part of the Acquire or Release versions, to ensure that nothing from outside +// the call is reordered between the operation and the memory barrier. This does +// not change the code generated, so has no or minimal impact on the +// NoBarrier operations. + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev; + int32_t temp; + + __asm__ __volatile__ ( // NOLINT + "0: \n\t" + "ldxr %w[prev], %[ptr] \n\t" // Load the previous value. + "cmp %w[prev], %w[old_value] \n\t" + "bne 1f \n\t" + "stxr %w[temp], %w[new_value], %[ptr] \n\t" // Try to store the new value. + "cbnz %w[temp], 0b \n\t" // Retry if it did not work. + "1: \n\t" + : [prev]"=&r" (prev), + [temp]"=&r" (temp), + [ptr]"+Q" (*ptr) + : [old_value]"IJr" (old_value), + [new_value]"r" (new_value) + : "cc", "memory" + ); // NOLINT + + return prev; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 result; + int32_t temp; + + __asm__ __volatile__ ( // NOLINT + "0: \n\t" + "ldxr %w[result], %[ptr] \n\t" // Load the previous value. + "stxr %w[temp], %w[new_value], %[ptr] \n\t" // Try to store the new value. + "cbnz %w[temp], 0b \n\t" // Retry if it did not work. + : [result]"=&r" (result), + [temp]"=&r" (temp), + [ptr]"+Q" (*ptr) + : [new_value]"r" (new_value) + : "memory" + ); // NOLINT + + return result; +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + Atomic32 result; + int32_t temp; + + __asm__ __volatile__ ( // NOLINT + "0: \n\t" + "ldxr %w[result], %[ptr] \n\t" // Load the previous value. + "add %w[result], %w[result], %w[increment]\n\t" + "stxr %w[temp], %w[result], %[ptr] \n\t" // Try to store the result. + "cbnz %w[temp], 0b \n\t" // Retry on failure. + : [result]"=&r" (result), + [temp]"=&r" (temp), + [ptr]"+Q" (*ptr) + : [increment]"IJr" (increment) + : "memory" + ); // NOLINT + + return result; +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + MemoryBarrier(); + Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment); + MemoryBarrier(); + + return result; +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + MemoryBarrier(); + + return prev; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + MemoryBarrier(); + Atomic32 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + + return prev; +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + __asm__ __volatile__ ( // NOLINT + "stlr %w[value], %[ptr] \n\t" + : [ptr]"=Q" (*ptr) + : [value]"r" (value) + : "memory" + ); // NOLINT +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value; + + __asm__ __volatile__ ( // NOLINT + "ldar %w[value], %[ptr] \n\t" + : [value]"=r" (value) + : [ptr]"Q" (*ptr) + : "memory" + ); // NOLINT + + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +// 64-bit versions of the operations. +// See the 32-bit versions for comments. + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev; + int32_t temp; + + __asm__ __volatile__ ( // NOLINT + "0: \n\t" + "ldxr %[prev], %[ptr] \n\t" + "cmp %[prev], %[old_value] \n\t" + "bne 1f \n\t" + "stxr %w[temp], %[new_value], %[ptr] \n\t" + "cbnz %w[temp], 0b \n\t" + "1: \n\t" + : [prev]"=&r" (prev), + [temp]"=&r" (temp), + [ptr]"+Q" (*ptr) + : [old_value]"IJr" (old_value), + [new_value]"r" (new_value) + : "cc", "memory" + ); // NOLINT + + return prev; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + Atomic64 result; + int32_t temp; + + __asm__ __volatile__ ( // NOLINT + "0: \n\t" + "ldxr %[result], %[ptr] \n\t" + "stxr %w[temp], %[new_value], %[ptr] \n\t" + "cbnz %w[temp], 0b \n\t" + : [result]"=&r" (result), + [temp]"=&r" (temp), + [ptr]"+Q" (*ptr) + : [new_value]"r" (new_value) + : "memory" + ); // NOLINT + + return result; +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + Atomic64 result; + int32_t temp; + + __asm__ __volatile__ ( // NOLINT + "0: \n\t" + "ldxr %[result], %[ptr] \n\t" + "add %[result], %[result], %[increment] \n\t" + "stxr %w[temp], %[result], %[ptr] \n\t" + "cbnz %w[temp], 0b \n\t" + : [result]"=&r" (result), + [temp]"=&r" (temp), + [ptr]"+Q" (*ptr) + : [increment]"IJr" (increment) + : "memory" + ); // NOLINT + + return result; +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + MemoryBarrier(); + Atomic64 result = NoBarrier_AtomicIncrement(ptr, increment); + MemoryBarrier(); + + return result; +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + MemoryBarrier(); + + return prev; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + MemoryBarrier(); + Atomic64 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + + return prev; +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + __asm__ __volatile__ ( // NOLINT + "stlr %x[value], %[ptr] \n\t" + : [ptr]"=Q" (*ptr) + : [value]"r" (value) + : "memory" + ); // NOLINT +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value; + + __asm__ __volatile__ ( // NOLINT + "ldar %x[value], %[ptr] \n\t" + : [value]"=r" (value) + : [ptr]"Q" (*ptr) + : "memory" + ); // NOLINT + + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return *ptr; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h b/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h new file mode 100644 index 0000000..1f4dedc --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h @@ -0,0 +1,151 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 file is an internal atomic implementation, use atomicops.h instead. +// +// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_ + +namespace google { +namespace protobuf { +namespace internal { + +// 0xffff0fc0 is the hard coded address of a function provided by +// the kernel which implements an atomic compare-exchange. On older +// ARM architecture revisions (pre-v6) this may be implemented using +// a syscall. This address is stable, and in active use (hard coded) +// by at least glibc-2.7 and the Android C library. +typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value, + Atomic32 new_value, + volatile Atomic32* ptr); +LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) = + (LinuxKernelCmpxchgFunc) 0xffff0fc0; + +typedef void (*LinuxKernelMemoryBarrierFunc)(void); +LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) = + (LinuxKernelMemoryBarrierFunc) 0xffff0fa0; + + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value = *ptr; + do { + if (!pLinuxKernelCmpxchg(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (pLinuxKernelCmpxchg(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return Barrier_AtomicIncrement(ptr, increment); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + for (;;) { + // Atomic exchange the old value with an incremented one. + Atomic32 old_value = *ptr; + Atomic32 new_value = old_value + increment; + if (pLinuxKernelCmpxchg(old_value, new_value, + const_cast(ptr)) == 0) { + // The exchange took place as expected. + return new_value; + } + // Otherwise, *ptr changed mid-loop and we need to retry. + } +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void MemoryBarrier() { + pLinuxKernelMemoryBarrier(); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h b/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h new file mode 100644 index 0000000..f050769 --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h @@ -0,0 +1,146 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 file is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_ + +// For _smp_cmpxchg() +#include + +namespace google { +namespace protobuf { +namespace internal { + +inline Atomic32 QNXCmpxchg(Atomic32 old_value, + Atomic32 new_value, + volatile Atomic32* ptr) { + return static_cast( + _smp_cmpxchg((volatile unsigned *)ptr, + (unsigned)old_value, + (unsigned)new_value)); +} + + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value = *ptr; + do { + if (!QNXCmpxchg(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (QNXCmpxchg(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return Barrier_AtomicIncrement(ptr, increment); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + for (;;) { + // Atomic exchange the old value with an incremented one. + Atomic32 old_value = *ptr; + Atomic32 new_value = old_value + increment; + if (QNXCmpxchg(old_value, new_value, + const_cast(ptr)) == 0) { + // The exchange took place as expected. + return new_value; + } + // Otherwise, *ptr changed mid-loop and we need to retry. + } +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void MemoryBarrier() { + __sync_synchronize(); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h b/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h new file mode 100644 index 0000000..e9d8679 --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h @@ -0,0 +1,122 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 file is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ + +// AtomicWord is a synonym for intptr_t, and Atomic32 is a synonym for int32, +// which in turn means int. On some LP32 platforms, intptr_t is an int, but +// on others, it's a long. When AtomicWord and Atomic32 are based on different +// fundamental types, their pointers are incompatible. +// +// This file defines function overloads to allow both AtomicWord and Atomic32 +// data to be used with this interface. +// +// On LP64 platforms, AtomicWord and Atomic64 are both always long, +// so this problem doesn't occur. + +#if !defined(GOOGLE_PROTOBUF_ARCH_64_BIT) + +namespace google { +namespace protobuf { +namespace internal { + +inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return NoBarrier_CompareAndSwap( + reinterpret_cast(ptr), old_value, new_value); +} + +inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr, + AtomicWord new_value) { + return NoBarrier_AtomicExchange( + reinterpret_cast(ptr), new_value); +} + +inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr, + AtomicWord increment) { + return NoBarrier_AtomicIncrement( + reinterpret_cast(ptr), increment); +} + +inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr, + AtomicWord increment) { + return Barrier_AtomicIncrement( + reinterpret_cast(ptr), increment); +} + +inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return Acquire_CompareAndSwap( + reinterpret_cast(ptr), old_value, new_value); +} + +inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return Release_CompareAndSwap( + reinterpret_cast(ptr), old_value, new_value); +} + +inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) { + NoBarrier_Store(reinterpret_cast(ptr), value); +} + +inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) { + return Acquire_Store(reinterpret_cast(ptr), value); +} + +inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { + return Release_Store(reinterpret_cast(ptr), value); +} + +inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) { + return NoBarrier_Load(reinterpret_cast(ptr)); +} + +inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) { + return Acquire_Load(reinterpret_cast(ptr)); +} + +inline AtomicWord Release_Load(volatile const AtomicWord* ptr) { + return Release_Load(reinterpret_cast(ptr)); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // !defined(GOOGLE_PROTOBUF_ARCH_64_BIT) + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h new file mode 100644 index 0000000..e30bb44 --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h @@ -0,0 +1,137 @@ +// Copyright 2013 Red Hat 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 Red Hat 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 file is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_ + +namespace google { +namespace protobuf { +namespace internal { + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + __atomic_compare_exchange_n(ptr, &old_value, new_value, true, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); + return old_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + return __atomic_exchange_n(ptr, new_value, __ATOMIC_RELAXED); +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return __atomic_add_fetch(ptr, increment, __ATOMIC_RELAXED); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return __atomic_add_fetch(ptr, increment, __ATOMIC_SEQ_CST); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + __atomic_compare_exchange(ptr, &old_value, &new_value, true, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + return old_value; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + __atomic_compare_exchange_n(ptr, &old_value, new_value, true, + __ATOMIC_RELEASE, __ATOMIC_ACQUIRE); + return old_value; +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + __atomic_store_n(ptr, value, __ATOMIC_RELAXED); +} + +inline void MemoryBarrier() { + __sync_synchronize(); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + __atomic_store_n(ptr, value, __ATOMIC_ACQUIRE); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + __atomic_store_n(ptr, value, __ATOMIC_RELEASE); +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return __atomic_load_n(ptr, __ATOMIC_RELAXED); +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + return __atomic_load_n(ptr, __ATOMIC_RELEASE); +} + +#ifdef __LP64__ + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + __atomic_store_n(ptr, value, __ATOMIC_RELEASE); +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + __atomic_compare_exchange_n(ptr, &old_value, new_value, true, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + return old_value; +} + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + __atomic_compare_exchange_n(ptr, &old_value, new_value, true, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); + return old_value; +} + +#endif // defined(__LP64__) + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_macosx.h b/src/google/protobuf/stubs/atomicops_internals_macosx.h new file mode 100644 index 0000000..f9b7581 --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_macosx.h @@ -0,0 +1,225 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 file is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MACOSX_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MACOSX_H_ + +#include + +namespace google { +namespace protobuf { +namespace internal { + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + do { + if (OSAtomicCompareAndSwap32(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap32(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return OSAtomicAdd32(increment, const_cast(ptr)); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return OSAtomicAdd32Barrier(increment, const_cast(ptr)); +} + +inline void MemoryBarrier() { + OSMemoryBarrier(); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + do { + if (OSAtomicCompareAndSwap32Barrier(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return Acquire_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +#ifdef __LP64__ + +// 64-bit implementation on 64-bit platform + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value; + do { + if (OSAtomicCompareAndSwap64(old_value, new_value, + reinterpret_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + Atomic64 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap64(old_value, new_value, + reinterpret_cast(ptr))); + return old_value; +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return OSAtomicAdd64(increment, reinterpret_cast(ptr)); +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return OSAtomicAdd64Barrier(increment, + reinterpret_cast(ptr)); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value; + do { + if (OSAtomicCompareAndSwap64Barrier( + old_value, new_value, reinterpret_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + // The lib kern interface does not distinguish between + // Acquire and Release memory barriers; they are equivalent. + return Acquire_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return *ptr; +} + +#endif // defined(__LP64__) + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MACOSX_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h b/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h new file mode 100644 index 0000000..cf79a13 --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h @@ -0,0 +1,313 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 file is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MIPS_GCC_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MIPS_GCC_H_ + +#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") + +namespace google { +namespace protobuf { +namespace internal { + +// Atomically execute: +// result = *ptr; +// if (*ptr == old_value) +// *ptr = new_value; +// return result; +// +// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". +// Always return the old value of "*ptr" +// +// This routine implies no memory barriers. +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev, tmp; + __asm__ __volatile__(".set push\n" + ".set noreorder\n" + "1:\n" + "ll %0, %5\n" // prev = *ptr + "bne %0, %3, 2f\n" // if (prev != old_value) goto 2 + "move %2, %4\n" // tmp = new_value + "sc %2, %1\n" // *ptr = tmp (with atomic check) + "beqz %2, 1b\n" // start again on atomic error + "nop\n" // delay slot nop + "2:\n" + ".set pop\n" + : "=&r" (prev), "=m" (*ptr), "=&r" (tmp) + : "Ir" (old_value), "r" (new_value), "m" (*ptr) + : "memory"); + return prev; +} + +// Atomically store new_value into *ptr, returning the previous value held in +// *ptr. This routine implies no memory barriers. +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 temp, old; + __asm__ __volatile__(".set push\n" + ".set noreorder\n" + "1:\n" + "ll %1, %4\n" // old = *ptr + "move %0, %3\n" // temp = new_value + "sc %0, %2\n" // *ptr = temp (with atomic check) + "beqz %0, 1b\n" // start again on atomic error + "nop\n" // delay slot nop + ".set pop\n" + : "=&r" (temp), "=&r" (old), "=m" (*ptr) + : "r" (new_value), "m" (*ptr) + : "memory"); + + return old; +} + +// Atomically increment *ptr by "increment". Returns the new value of +// *ptr with the increment applied. This routine implies no memory barriers. +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + Atomic32 temp, temp2; + + __asm__ __volatile__(".set push\n" + ".set noreorder\n" + "1:\n" + "ll %0, %4\n" // temp = *ptr + "addu %1, %0, %3\n" // temp2 = temp + increment + "sc %1, %2\n" // *ptr = temp2 (with atomic check) + "beqz %1, 1b\n" // start again on atomic error + "addu %1, %0, %3\n" // temp2 = temp + increment + ".set pop\n" + : "=&r" (temp), "=&r" (temp2), "=m" (*ptr) + : "Ir" (increment), "m" (*ptr) + : "memory"); + // temp2 now holds the final value. + return temp2; +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + ATOMICOPS_COMPILER_BARRIER(); + Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment); + ATOMICOPS_COMPILER_BARRIER(); + return res; +} + +// "Acquire" operations +// ensure that no later memory access can be reordered ahead of the operation. +// "Release" operations ensure that no previous memory access can be reordered +// after the operation. "Barrier" operations have both "Acquire" and "Release" +// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory +// access. +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + ATOMICOPS_COMPILER_BARRIER(); + Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + ATOMICOPS_COMPILER_BARRIER(); + return res; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + ATOMICOPS_COMPILER_BARRIER(); + Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + ATOMICOPS_COMPILER_BARRIER(); + return res; +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void MemoryBarrier() { + __asm__ __volatile__("sync" : : : "memory"); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +#if defined(__LP64__) +// 64-bit versions of the atomic ops. + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev, tmp; + __asm__ __volatile__(".set push\n" + ".set noreorder\n" + "1:\n" + "lld %0, %5\n" // prev = *ptr + "bne %0, %3, 2f\n" // if (prev != old_value) goto 2 + "move %2, %4\n" // tmp = new_value + "scd %2, %1\n" // *ptr = tmp (with atomic check) + "beqz %2, 1b\n" // start again on atomic error + "nop\n" // delay slot nop + "2:\n" + ".set pop\n" + : "=&r" (prev), "=m" (*ptr), "=&r" (tmp) + : "Ir" (old_value), "r" (new_value), "m" (*ptr) + : "memory"); + return prev; +} + +// Atomically store new_value into *ptr, returning the previous value held in +// *ptr. This routine implies no memory barriers. +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + Atomic64 temp, old; + __asm__ __volatile__(".set push\n" + ".set noreorder\n" + "1:\n" + "lld %1, %4\n" // old = *ptr + "move %0, %3\n" // temp = new_value + "scd %0, %2\n" // *ptr = temp (with atomic check) + "beqz %0, 1b\n" // start again on atomic error + "nop\n" // delay slot nop + ".set pop\n" + : "=&r" (temp), "=&r" (old), "=m" (*ptr) + : "r" (new_value), "m" (*ptr) + : "memory"); + + return old; +} + +// Atomically increment *ptr by "increment". Returns the new value of +// *ptr with the increment applied. This routine implies no memory barriers. +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + Atomic64 temp, temp2; + + __asm__ __volatile__(".set push\n" + ".set noreorder\n" + "1:\n" + "lld %0, %4\n" // temp = *ptr + "daddu %1, %0, %3\n" // temp2 = temp + increment + "scd %1, %2\n" // *ptr = temp2 (with atomic check) + "beqz %1, 1b\n" // start again on atomic error + "daddu %1, %0, %3\n" // temp2 = temp + increment + ".set pop\n" + : "=&r" (temp), "=&r" (temp2), "=m" (*ptr) + : "Ir" (increment), "m" (*ptr) + : "memory"); + // temp2 now holds the final value. + return temp2; +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + MemoryBarrier(); + Atomic64 res = NoBarrier_AtomicIncrement(ptr, increment); + MemoryBarrier(); + return res; +} + +// "Acquire" operations +// ensure that no later memory access can be reordered ahead of the operation. +// "Release" operations ensure that no previous memory access can be reordered +// after the operation. "Barrier" operations have both "Acquire" and "Release" +// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory +// access. +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + MemoryBarrier(); + return res; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + MemoryBarrier(); + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return *ptr; +} +#endif + +} // namespace internal +} // namespace protobuf +} // namespace google + +#undef ATOMICOPS_COMPILER_BARRIER + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MIPS_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_pnacl.h b/src/google/protobuf/stubs/atomicops_internals_pnacl.h new file mode 100644 index 0000000..04a91a8 --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_pnacl.h @@ -0,0 +1,73 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 file is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ + +namespace google { +namespace protobuf { +namespace internal { + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return __sync_val_compare_and_swap(ptr, old_value, new_value); +} + +inline void MemoryBarrier() { + __sync_synchronize(); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 ret = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + MemoryBarrier(); + return ret; +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_tsan.h b/src/google/protobuf/stubs/atomicops_internals_tsan.h new file mode 100644 index 0000000..8112ee0 --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_tsan.h @@ -0,0 +1,219 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2013 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 file is an internal atomic implementation for compiler-based +// ThreadSanitizer (http://clang.llvm.org/docs/ThreadSanitizer.html). +// Use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TSAN_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TSAN_H_ + +#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") + +#include + +namespace google { +namespace protobuf { +namespace internal { + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 cmp = old_value; + __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value, + __tsan_memory_order_relaxed, __tsan_memory_order_relaxed); + return cmp; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr, + Atomic32 new_value) { + return __tsan_atomic32_exchange(ptr, new_value, + __tsan_memory_order_relaxed); +} + +inline Atomic32 Acquire_AtomicExchange(volatile Atomic32 *ptr, + Atomic32 new_value) { + return __tsan_atomic32_exchange(ptr, new_value, + __tsan_memory_order_acquire); +} + +inline Atomic32 Release_AtomicExchange(volatile Atomic32 *ptr, + Atomic32 new_value) { + return __tsan_atomic32_exchange(ptr, new_value, + __tsan_memory_order_release); +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr, + Atomic32 increment) { + return increment + __tsan_atomic32_fetch_add(ptr, increment, + __tsan_memory_order_relaxed); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr, + Atomic32 increment) { + return increment + __tsan_atomic32_fetch_add(ptr, increment, + __tsan_memory_order_acq_rel); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 cmp = old_value; + __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value, + __tsan_memory_order_acquire, __tsan_memory_order_acquire); + return cmp; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 cmp = old_value; + __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value, + __tsan_memory_order_release, __tsan_memory_order_relaxed); + return cmp; +} + +inline void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value) { + __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed); +} + +inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) { + __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed); + __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); +} + +inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) { + __tsan_atomic32_store(ptr, value, __tsan_memory_order_release); +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr) { + return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed); +} + +inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) { + return __tsan_atomic32_load(ptr, __tsan_memory_order_acquire); +} + +inline Atomic32 Release_Load(volatile const Atomic32 *ptr) { + __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); + return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed); +} + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 cmp = old_value; + __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value, + __tsan_memory_order_relaxed, __tsan_memory_order_relaxed); + return cmp; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr, + Atomic64 new_value) { + return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_relaxed); +} + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64 *ptr, + Atomic64 new_value) { + return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_acquire); +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64 *ptr, + Atomic64 new_value) { + return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_release); +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr, + Atomic64 increment) { + return increment + __tsan_atomic64_fetch_add(ptr, increment, + __tsan_memory_order_relaxed); +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr, + Atomic64 increment) { + return increment + __tsan_atomic64_fetch_add(ptr, increment, + __tsan_memory_order_acq_rel); +} + +inline void NoBarrier_Store(volatile Atomic64 *ptr, Atomic64 value) { + __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed); +} + +inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) { + __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed); + __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); +} + +inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) { + __tsan_atomic64_store(ptr, value, __tsan_memory_order_release); +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64 *ptr) { + return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed); +} + +inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) { + return __tsan_atomic64_load(ptr, __tsan_memory_order_acquire); +} + +inline Atomic64 Release_Load(volatile const Atomic64 *ptr) { + __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); + return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 cmp = old_value; + __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value, + __tsan_memory_order_acquire, __tsan_memory_order_acquire); + return cmp; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 cmp = old_value; + __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value, + __tsan_memory_order_release, __tsan_memory_order_relaxed); + return cmp; +} + +inline void MemoryBarrier() { + __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#undef ATOMICOPS_COMPILER_BARRIER + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TSAN_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc b/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc new file mode 100644 index 0000000..0774872 --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc @@ -0,0 +1,137 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 module gets enough CPU information to optimize the +// atomicops module on x86. + +#include + +#include + +// This file only makes sense with atomicops_internals_x86_gcc.h -- it +// depends on structs that are defined in that file. If atomicops.h +// doesn't sub-include that file, then we aren't needed, and shouldn't +// try to do anything. +#ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ + +// Inline cpuid instruction. In PIC compilations, %ebx contains the address +// of the global offset table. To avoid breaking such executables, this code +// must preserve that register's value across cpuid instructions. +#if defined(__i386__) +#define cpuid(a, b, c, d, inp) \ + asm("mov %%ebx, %%edi\n" \ + "cpuid\n" \ + "xchg %%edi, %%ebx\n" \ + : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) +#elif defined(__x86_64__) +#define cpuid(a, b, c, d, inp) \ + asm("mov %%rbx, %%rdi\n" \ + "cpuid\n" \ + "xchg %%rdi, %%rbx\n" \ + : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) +#endif + +#if defined(cpuid) // initialize the struct only on x86 + +namespace google { +namespace protobuf { +namespace internal { + +// Set the flags so that code will run correctly and conservatively, so even +// if we haven't been initialized yet, we're probably single threaded, and our +// default values should hopefully be pretty safe. +struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = { + false, // bug can't exist before process spawns multiple threads + false, // no SSE2 +}; + +namespace { + +// Initialize the AtomicOps_Internalx86CPUFeatures struct. +void AtomicOps_Internalx86CPUFeaturesInit() { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + + // Get vendor string (issue CPUID with eax = 0) + cpuid(eax, ebx, ecx, edx, 0); + char vendor[13]; + memcpy(vendor, &ebx, 4); + memcpy(vendor + 4, &edx, 4); + memcpy(vendor + 8, &ecx, 4); + vendor[12] = 0; + + // get feature flags in ecx/edx, and family/model in eax + cpuid(eax, ebx, ecx, edx, 1); + + int family = (eax >> 8) & 0xf; // family and model fields + int model = (eax >> 4) & 0xf; + if (family == 0xf) { // use extended family and model fields + family += (eax >> 20) & 0xff; + model += ((eax >> 16) & 0xf) << 4; + } + + // Opteron Rev E has a bug in which on very rare occasions a locked + // instruction doesn't act as a read-acquire barrier if followed by a + // non-locked read-modify-write instruction. Rev F has this bug in + // pre-release versions, but not in versions released to customers, + // so we test only for Rev E, which is family 15, model 32..63 inclusive. + if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD + family == 15 && + 32 <= model && model <= 63) { + AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true; + } else { + AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false; + } + + // edx bit 26 is SSE2 which we use to tell use whether we can use mfence + AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1); +} + +class AtomicOpsx86Initializer { + public: + AtomicOpsx86Initializer() { + AtomicOps_Internalx86CPUFeaturesInit(); + } +}; + +// A global to get use initialized on startup via static initialization :/ +AtomicOpsx86Initializer g_initer; + +} // namespace + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // __i386__ + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h b/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h new file mode 100644 index 0000000..5324dfb --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h @@ -0,0 +1,293 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 file is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ + +namespace google { +namespace protobuf { +namespace internal { + +// This struct is not part of the public API of this module; clients may not +// use it. +// Features of this x86. Values may not be correct before main() is run, +// but are set conservatively. +struct AtomicOps_x86CPUFeatureStruct { + bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence + // after acquire compare-and-swap. + bool has_sse2; // Processor has SSE2. +}; +extern struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures; + +#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") + +// 32-bit low-level operations on any platform. + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev; + __asm__ __volatile__("lock; cmpxchgl %1,%2" + : "=a" (prev) + : "q" (new_value), "m" (*ptr), "0" (old_value) + : "memory"); + return prev; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + __asm__ __volatile__("xchgl %1,%0" // The lock prefix is implicit for xchg. + : "=r" (new_value) + : "m" (*ptr), "0" (new_value) + : "memory"); + return new_value; // Now it's the previous value. +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + Atomic32 temp = increment; + __asm__ __volatile__("lock; xaddl %0,%1" + : "+r" (temp), "+m" (*ptr) + : : "memory"); + // temp now holds the old value of *ptr + return temp + increment; +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + Atomic32 temp = increment; + __asm__ __volatile__("lock; xaddl %0,%1" + : "+r" (temp), "+m" (*ptr) + : : "memory"); + // temp now holds the old value of *ptr + if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { + __asm__ __volatile__("lfence" : : : "memory"); + } + return temp + increment; +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { + __asm__ __volatile__("lfence" : : : "memory"); + } + return x; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +#if defined(__x86_64__) + +// 64-bit implementations of memory barrier can be simpler, because it +// "mfence" is guaranteed to exist. +inline void MemoryBarrier() { + __asm__ __volatile__("mfence" : : : "memory"); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +#else + +inline void MemoryBarrier() { + if (AtomicOps_Internalx86CPUFeatures.has_sse2) { + __asm__ __volatile__("mfence" : : : "memory"); + } else { // mfence is faster but not present on PIII + Atomic32 x = 0; + NoBarrier_AtomicExchange(&x, 0); // acts as a barrier on PIII + } +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + if (AtomicOps_Internalx86CPUFeatures.has_sse2) { + *ptr = value; + __asm__ __volatile__("mfence" : : : "memory"); + } else { + NoBarrier_AtomicExchange(ptr, value); + // acts as a barrier on PIII + } +} +#endif + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + ATOMICOPS_COMPILER_BARRIER(); + *ptr = value; // An x86 store acts as a release barrier. + // See comments in Atomic64 version of Release_Store(), below. +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; // An x86 load acts as a acquire barrier. + // See comments in Atomic64 version of Release_Store(), below. + ATOMICOPS_COMPILER_BARRIER(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +#if defined(__x86_64__) + +// 64-bit low-level operations on 64-bit platform. + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev; + __asm__ __volatile__("lock; cmpxchgq %1,%2" + : "=a" (prev) + : "q" (new_value), "m" (*ptr), "0" (old_value) + : "memory"); + return prev; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + __asm__ __volatile__("xchgq %1,%0" // The lock prefix is implicit for xchg. + : "=r" (new_value) + : "m" (*ptr), "0" (new_value) + : "memory"); + return new_value; // Now it's the previous value. +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + Atomic64 temp = increment; + __asm__ __volatile__("lock; xaddq %0,%1" + : "+r" (temp), "+m" (*ptr) + : : "memory"); + // temp now contains the previous value of *ptr + return temp + increment; +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + Atomic64 temp = increment; + __asm__ __volatile__("lock; xaddq %0,%1" + : "+r" (temp), "+m" (*ptr) + : : "memory"); + // temp now contains the previous value of *ptr + if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { + __asm__ __volatile__("lfence" : : : "memory"); + } + return temp + increment; +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + ATOMICOPS_COMPILER_BARRIER(); + + *ptr = value; // An x86 store acts as a release barrier + // for current AMD/Intel chips as of Jan 2008. + // See also Acquire_Load(), below. + + // When new chips come out, check: + // IA-32 Intel Architecture Software Developer's Manual, Volume 3: + // System Programming Guide, Chatper 7: Multiple-processor management, + // Section 7.2, Memory Ordering. + // Last seen at: + // http://developer.intel.com/design/pentium4/manuals/index_new.htm + // + // x86 stores/loads fail to act as barriers for a few instructions (clflush + // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are + // not generated by the compiler, and are rare. Users of these instructions + // need to know about cache behaviour in any case since all of these involve + // either flushing cache lines or non-temporal cache hints. +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; // An x86 load acts as a acquire barrier, + // for current AMD/Intel chips as of Jan 2008. + // See also Release_Store(), above. + ATOMICOPS_COMPILER_BARRIER(); + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return *ptr; +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { + __asm__ __volatile__("lfence" : : : "memory"); + } + return x; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +#endif // defined(__x86_64__) + +} // namespace internal +} // namespace protobuf +} // namespace google + +#undef ATOMICOPS_COMPILER_BARRIER + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc b/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc new file mode 100644 index 0000000..0b35979 --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc @@ -0,0 +1,112 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// The compilation of extension_set.cc fails when windows.h is included. +// Therefore we move the code depending on windows.h to this separate cc file. + +// Don't compile this file for people not concerned about thread safety. +#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY + +#include + +#ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ + +#include + +namespace google { +namespace protobuf { +namespace internal { + +inline void MemoryBarrier() { + // We use MemoryBarrier from WinNT.h + ::MemoryBarrier(); +} + +Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + LONG result = InterlockedCompareExchange( + reinterpret_cast(ptr), + static_cast(new_value), + static_cast(old_value)); + return static_cast(result); +} + +Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + LONG result = InterlockedExchange( + reinterpret_cast(ptr), + static_cast(new_value)); + return static_cast(result); +} + +Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return InterlockedExchangeAdd( + reinterpret_cast(ptr), + static_cast(increment)) + increment; +} + +#if defined(_WIN64) + +// 64-bit low-level operations on 64-bit platform. + +Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + PVOID result = InterlockedCompareExchangePointer( + reinterpret_cast(ptr), + reinterpret_cast(new_value), reinterpret_cast(old_value)); + return reinterpret_cast(result); +} + +Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + PVOID result = InterlockedExchangePointer( + reinterpret_cast(ptr), + reinterpret_cast(new_value)); + return reinterpret_cast(result); +} + +Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return InterlockedExchangeAdd64( + reinterpret_cast(ptr), + static_cast(increment)) + increment; +} + +#endif // defined(_WIN64) + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ +#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY diff --git a/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h b/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h new file mode 100644 index 0000000..6f9869d --- /dev/null +++ b/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h @@ -0,0 +1,150 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 file is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ + +namespace google { +namespace protobuf { +namespace internal { + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return Barrier_AtomicIncrement(ptr, increment); +} + +#if !(defined(_MSC_VER) && _MSC_VER >= 1400) +#error "We require at least vs2005 for MemoryBarrier" +#endif + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + NoBarrier_AtomicExchange(ptr, value); + // acts as a barrier in this implementation +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; // works w/o barrier for current Intel chips as of June 2005 + // See comments in Atomic64 version of Release_Store() below. +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +#if defined(_WIN64) + +// 64-bit low-level operations on 64-bit platform. + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return Barrier_AtomicIncrement(ptr, increment); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + NoBarrier_AtomicExchange(ptr, value); + // acts as a barrier in this implementation +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; // works w/o barrier for current Intel chips as of June 2005 + + // When new chips come out, check: + // IA-32 Intel Architecture Software Developer's Manual, Volume 3: + // System Programming Guide, Chatper 7: Multiple-processor management, + // Section 7.2, Memory Ordering. + // Last seen at: + // http://developer.intel.com/design/pentium4/manuals/index_new.htm +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return *ptr; +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +#endif // defined(_WIN64) + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc index 1e2d68d..a4de636 100644 --- a/src/google/protobuf/stubs/common.cc +++ b/src/google/protobuf/stubs/common.cc @@ -110,13 +110,13 @@ void DefaultLogHandler(LogLevel level, const char* filename, int line, // We use fprintf() instead of cerr because we want this to work at static // initialization time. - fprintf(stderr, "libprotobuf %s %s:%d] %s\n", + fprintf(stderr, "[libprotobuf %s %s:%d] %s\n", level_names[level], filename, line, message.c_str()); fflush(stderr); // Needed on MSVC. } -void NullLogHandler(LogLevel level, const char* filename, int line, - const string& message) { +void NullLogHandler(LogLevel /* level */, const char* /* filename */, + int /* line */, const string& /* message */) { // Nothing. } @@ -183,15 +183,19 @@ void LogMessage::Finish() { if (level_ != LOGLEVEL_FATAL) { InitLogSilencerCountOnce(); MutexLock lock(log_silencer_count_mutex_); - suppress = internal::log_silencer_count_ > 0; + suppress = log_silencer_count_ > 0; } if (!suppress) { - internal::log_handler_(level_, filename_, line_, message_); + log_handler_(level_, filename_, line_, message_); } if (level_ == LOGLEVEL_FATAL) { +#if PROTOBUF_USE_EXCEPTIONS + throw FatalException(filename_, line_, message_); +#else abort(); +#endif } } @@ -316,6 +320,24 @@ void Mutex::AssertHeld() { #endif // =================================================================== +// emulates google3/util/endian/endian.h +// +// TODO(xiaofeng): PROTOBUF_LITTLE_ENDIAN is unfortunately defined in +// google/protobuf/io/coded_stream.h and therefore can not be used here. +// Maybe move that macro definition here in the furture. +uint32 ghtonl(uint32 x) { + union { + uint32 result; + uint8 result_array[4]; + }; + result_array[0] = static_cast(x >> 24); + result_array[1] = static_cast((x >> 16) & 0xFF); + result_array[2] = static_cast((x >> 8) & 0xFF); + result_array[3] = static_cast(x & 0xFF); + return result; +} + +// =================================================================== // Shutdown support. namespace internal { @@ -361,5 +383,13 @@ void ShutdownProtobufLibrary() { internal::shutdown_functions_mutex = NULL; } +#if PROTOBUF_USE_EXCEPTIONS +FatalException::~FatalException() throw() {} + +const char* FatalException::what() const throw() { + return message_.c_str(); +} +#endif + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index 551ee4a..800b700 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h @@ -48,13 +48,43 @@ #include #endif +#ifndef PROTOBUF_USE_EXCEPTIONS +#if defined(_MSC_VER) && defined(_CPPUNWIND) + #define PROTOBUF_USE_EXCEPTIONS 1 +#elif defined(__EXCEPTIONS) + #define PROTOBUF_USE_EXCEPTIONS 1 +#else + #define PROTOBUF_USE_EXCEPTIONS 0 +#endif +#endif + +#if PROTOBUF_USE_EXCEPTIONS +#include +#endif + +#if defined(_WIN32) && defined(GetMessage) +// Allow GetMessage to be used as a valid method name in protobuf classes. +// windows.h defines GetMessage() as a macro. Let's re-define it as an inline +// function. The inline function should be equivalent for C++ users. +inline BOOL GetMessage_Win32( + LPMSG lpMsg, HWND hWnd, + UINT wMsgFilterMin, UINT wMsgFilterMax) { + return GetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); +} +#undef GetMessage +inline BOOL GetMessage( + LPMSG lpMsg, HWND hWnd, + UINT wMsgFilterMin, UINT wMsgFilterMax) { + return GetMessage_Win32(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); +} +#endif + + namespace std {} namespace google { namespace protobuf { -using namespace std; // Don't do this at home, kids. - #undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS #define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ TypeName(const TypeName&); \ @@ -83,24 +113,24 @@ namespace internal { // The current version, represented as a single integer to make comparison // easier: major * 10^6 + minor * 10^3 + micro -#define GOOGLE_PROTOBUF_VERSION 2003000 +#define GOOGLE_PROTOBUF_VERSION 2006000 // The minimum library version which works with the current version of the // headers. -#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 2003000 +#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 2006000 // The minimum header version which works with the current version of // the library. This constant should only be used by protoc's C++ code // generator. -static const int kMinHeaderVersionForLibrary = 2003000; +static const int kMinHeaderVersionForLibrary = 2006000; // The minimum protoc version which works with the current version of the // headers. -#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 2003000 +#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 2006000 // The minimum header version which works with the current version of // protoc. This constant should only be used in VerifyVersion(). -static const int kMinHeaderVersionForProtoc = 2003000; +static const int kMinHeaderVersionForProtoc = 2006000; // Verifies that the headers and libraries are compatible. Use the macro // below to call this. @@ -108,7 +138,7 @@ void LIBPROTOBUF_EXPORT VerifyVersion(int headerVersion, int minLibraryVersion, const char* filename); // Converts a numeric version number to a string. -string LIBPROTOBUF_EXPORT VersionString(int version); +std::string LIBPROTOBUF_EXPORT VersionString(int version); } // namespace internal @@ -351,6 +381,7 @@ struct CompileAssert { typedef ::google::protobuf::internal::CompileAssert<(bool(expr))> \ msg[bool(expr) ? 1 : -1] + // Implementation details of COMPILE_ASSERT: // // - COMPILE_ASSERT works by defining an array type that has -1 @@ -618,7 +649,7 @@ class LIBPROTOBUF_EXPORT LogMessage { LogMessage(LogLevel level, const char* filename, int line); ~LogMessage(); - LogMessage& operator<<(const string& value); + LogMessage& operator<<(const std::string& value); LogMessage& operator<<(const char* value); LogMessage& operator<<(char value); LogMessage& operator<<(int value); @@ -634,7 +665,7 @@ class LIBPROTOBUF_EXPORT LogMessage { LogLevel level_; const char* filename_; int line_; - string message_; + std::string message_; }; // Used to make the entire "LOG(BLAH) << etc." expression have a void return @@ -654,12 +685,14 @@ class LIBPROTOBUF_EXPORT LogFinisher { #undef GOOGLE_LOG_IF #undef GOOGLE_CHECK +#undef GOOGLE_CHECK_OK #undef GOOGLE_CHECK_EQ #undef GOOGLE_CHECK_NE #undef GOOGLE_CHECK_LT #undef GOOGLE_CHECK_LE #undef GOOGLE_CHECK_GT #undef GOOGLE_CHECK_GE +#undef GOOGLE_CHECK_NOTNULL #undef GOOGLE_DLOG #undef GOOGLE_DCHECK @@ -679,6 +712,7 @@ class LIBPROTOBUF_EXPORT LogFinisher { #define GOOGLE_CHECK(EXPRESSION) \ GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " +#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(A) #define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B)) #define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B)) #define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B)) @@ -686,6 +720,19 @@ class LIBPROTOBUF_EXPORT LogFinisher { #define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B)) #define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B)) +namespace internal { +template +T* CheckNotNull(const char* /* file */, int /* line */, + const char* name, T* val) { + if (val == NULL) { + GOOGLE_LOG(FATAL) << name; + } + return val; +} +} // namespace internal +#define GOOGLE_CHECK_NOTNULL(A) \ + internal::CheckNotNull(__FILE__, __LINE__, "'" #A "' must not be NULL", (A)) + #ifdef NDEBUG #define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false) @@ -713,7 +760,7 @@ class LIBPROTOBUF_EXPORT LogFinisher { #endif // !NDEBUG typedef void LogHandler(LogLevel level, const char* filename, int line, - const string& message); + const std::string& message); // The protobuf library sometimes writes warning and error messages to // stderr. These messages are primarily useful for developers, but may @@ -825,8 +872,9 @@ class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure { ~FunctionClosure0(); void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes function_(); - if (self_deleting_) delete this; + if (needs_delete) delete this; } private: @@ -844,8 +892,9 @@ class MethodClosure0 : public Closure { ~MethodClosure0() {} void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes (object_->*method_)(); - if (self_deleting_) delete this; + if (needs_delete) delete this; } private: @@ -866,8 +915,9 @@ class FunctionClosure1 : public Closure { ~FunctionClosure1() {} void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes function_(arg1_); - if (self_deleting_) delete this; + if (needs_delete) delete this; } private: @@ -888,8 +938,9 @@ class MethodClosure1 : public Closure { ~MethodClosure1() {} void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes (object_->*method_)(arg1_); - if (self_deleting_) delete this; + if (needs_delete) delete this; } private: @@ -911,8 +962,9 @@ class FunctionClosure2 : public Closure { ~FunctionClosure2() {} void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes function_(arg1_, arg2_); - if (self_deleting_) delete this; + if (needs_delete) delete this; } private: @@ -934,8 +986,9 @@ class MethodClosure2 : public Closure { ~MethodClosure2() {} void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes (object_->*method_)(arg1_, arg2_); - if (self_deleting_) delete this; + if (needs_delete) delete this; } private: @@ -1104,20 +1157,10 @@ using internal::WriterMutexLock; using internal::MutexLockMaybe; // =================================================================== -// from google3/base/type_traits.h +// from google3/util/utf8/public/unilib.h namespace internal { -// Specified by TR1 [4.7.4] Pointer modifications. -template struct remove_pointer { typedef T type; }; -template struct remove_pointer { typedef T type; }; -template struct remove_pointer { typedef T type; }; -template struct remove_pointer { typedef T type; }; -template struct remove_pointer { - typedef T type; }; - -// =================================================================== - // Checks if the buffer contains structurally-valid UTF-8. Implemented in // structurally_valid.cc. LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len); @@ -1125,6 +1168,10 @@ LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len); } // namespace internal // =================================================================== +// from google3/util/endian/endian.h +LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x); + +// =================================================================== // Shutdown support. // Shut down the entire protocol buffers library, deleting all static-duration @@ -1149,6 +1196,30 @@ LIBPROTOBUF_EXPORT void OnShutdown(void (*func)()); } // namespace internal +#if PROTOBUF_USE_EXCEPTIONS +class FatalException : public std::exception { + public: + FatalException(const char* filename, int line, const std::string& message) + : filename_(filename), line_(line), message_(message) {} + virtual ~FatalException() throw(); + + virtual const char* what() const throw(); + + const char* filename() const { return filename_; } + int line() const { return line_; } + const std::string& message() const { return message_; } + + private: + const char* filename_; + const int line_; + const std::string message_; +}; +#endif + +// This is at the end of the file instead of the beginning to work around a bug +// in some versions of MSVC. +using namespace std; // Don't do this at home, kids. + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc index 32c1d08..43cd6d0 100644 --- a/src/google/protobuf/stubs/common_unittest.cc +++ b/src/google/protobuf/stubs/common_unittest.cc @@ -94,9 +94,9 @@ TEST(LoggingTest, DefaultLogging) { string text = GetCapturedTestStderr(); EXPECT_EQ( - "libprotobuf INFO "__FILE__":" + SimpleItoa(line + 1) + "] A message.\n" - "libprotobuf WARNING "__FILE__":" + SimpleItoa(line + 2) + "] A warning.\n" - "libprotobuf ERROR "__FILE__":" + SimpleItoa(line + 3) + "] An error.\n", + "[libprotobuf INFO "__FILE__":" + SimpleItoa(line + 1) + "] A message.\n" + "[libprotobuf WARNING "__FILE__":" + SimpleItoa(line + 2) + "] A warning.\n" + "[libprotobuf ERROR "__FILE__":" + SimpleItoa(line + 3) + "] An error.\n", text); } @@ -182,11 +182,17 @@ class ClosureTest : public testing::Test { a_ = 0; b_ = NULL; c_.clear(); + permanent_closure_ = NULL; + } + + void DeleteClosureInCallback() { + delete permanent_closure_; } int a_; const char* b_; string c_; + Closure* permanent_closure_; static ClosureTest* current_instance_; }; @@ -340,6 +346,12 @@ TEST_F(ClosureTest, TestPermanentClosureMethod2) { delete closure; } +TEST_F(ClosureTest, TestPermanentClosureDeleteInCallback) { + permanent_closure_ = NewPermanentCallback((ClosureTest*) this, + &ClosureTest::DeleteClosureInCallback); + permanent_closure_->Run(); +} + } // anonymous namespace } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h index 822d605..f7d1071 100644 --- a/src/google/protobuf/stubs/hash.h +++ b/src/google/protobuf/stubs/hash.h @@ -90,12 +90,16 @@ template , typename EqualKey = int > class hash_map : public std::map { + public: + hash_map(int = 0) {} }; template , typename EqualKey = int > class hash_set : public std::set { + public: + hash_set(int = 0) {} }; #elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) @@ -123,6 +127,8 @@ template class hash_map : public HASH_NAMESPACE::hash_map< Key, Data, HashFcn> { + public: + hash_map(int = 0) {} }; template class hash_set : public HASH_NAMESPACE::hash_set< Key, HashFcn> { + public: + hash_set(int = 0) {} }; #else @@ -163,6 +171,8 @@ template > class hash_map : public HASH_NAMESPACE::HASH_MAP_CLASS< Key, Data, HashFcn, EqualKey> { + public: + hash_map(int = 0) {} }; template > class hash_set : public HASH_NAMESPACE::HASH_SET_CLASS< Key, HashFcn, EqualKey> { + public: + hash_set(int = 0) {} }; #endif diff --git a/src/google/protobuf/stubs/map_util.h b/src/google/protobuf/stubs/map_util.h new file mode 100644 index 0000000..fb2f5f3 --- /dev/null +++ b/src/google/protobuf/stubs/map_util.h @@ -0,0 +1,771 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// from google3/util/gtl/map_util.h +// Author: Anton Carver + +#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ +#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ + +#include +#include +#include +#include +#include + +#include + +namespace google { +namespace protobuf { +namespace internal { +// Local implementation of RemoveConst to avoid including base/type_traits.h. +template struct RemoveConst { typedef T type; }; +template struct RemoveConst : RemoveConst {}; +} // namespace internal + +// +// Find*() +// + +// Returns a const reference to the value associated with the given key if it +// exists. Crashes otherwise. +// +// This is intended as a replacement for operator[] as an rvalue (for reading) +// when the key is guaranteed to exist. +// +// operator[] for lookup is discouraged for several reasons: +// * It has a side-effect of inserting missing keys +// * It is not thread-safe (even when it is not inserting, it can still +// choose to resize the underlying storage) +// * It invalidates iterators (when it chooses to resize) +// * It default constructs a value object even if it doesn't need to +// +// This version assumes the key is printable, and includes it in the fatal log +// message. +template +const typename Collection::value_type::second_type& +FindOrDie(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key; + return it->second; +} + +// Same as above, but returns a non-const reference. +template +typename Collection::value_type::second_type& +FindOrDie(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key; + return it->second; +} + +// Same as FindOrDie above, but doesn't log the key on failure. +template +const typename Collection::value_type::second_type& +FindOrDieNoPrint(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found"; + return it->second; +} + +// Same as above, but returns a non-const reference. +template +typename Collection::value_type::second_type& +FindOrDieNoPrint(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found"; + return it->second; +} + +// Returns a const reference to the value associated with the given key if it +// exists, otherwise returns a const reference to the provided default value. +// +// WARNING: If a temporary object is passed as the default "value," +// this function will return a reference to that temporary object, +// which will be destroyed at the end of the statement. A common +// example: if you have a map with string values, and you pass a char* +// as the default "value," either use the returned value immediately +// or store it in a string (not string&). +// Details: http://go/findwithdefault +template +const typename Collection::value_type::second_type& +FindWithDefault(const Collection& collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return value; + } + return it->second; +} + +// Returns a pointer to the const value associated with the given key if it +// exists, or NULL otherwise. +template +const typename Collection::value_type::second_type* +FindOrNull(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + return &it->second; +} + +// Same as above but returns a pointer to the non-const value. +template +typename Collection::value_type::second_type* +FindOrNull(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + return &it->second; +} + +// Returns the pointer value associated with the given key. If none is found, +// NULL is returned. The function is designed to be used with a map of keys to +// pointers. +// +// This function does not distinguish between a missing key and a key mapped +// to a NULL value. +template +typename Collection::value_type::second_type +FindPtrOrNull(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return typename Collection::value_type::second_type(); + } + return it->second; +} + +// Same as above, except takes non-const reference to collection. +// +// This function is needed for containers that propagate constness to the +// pointee, such as boost::ptr_map. +template +typename Collection::value_type::second_type +FindPtrOrNull(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + if (it == collection.end()) { + return typename Collection::value_type::second_type(); + } + return it->second; +} + +// Finds the pointer value associated with the given key in a map whose values +// are linked_ptrs. Returns NULL if key is not found. +template +typename Collection::value_type::second_type::element_type* +FindLinkedPtrOrNull(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + // Since linked_ptr::get() is a const member returning a non const, + // we do not need a version of this function taking a non const collection. + return it->second.get(); +} + +// Same as above, but dies if the key is not found. +template +typename Collection::value_type::second_type::element_type& +FindLinkedPtrOrDie(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + CHECK(it != collection.end()) << "key not found: " << key; + // Since linked_ptr::operator*() is a const member returning a non const, + // we do not need a version of this function taking a non const collection. + return *it->second; +} + +// Finds the value associated with the given key and copies it to *value (if not +// NULL). Returns false if the key was not found, true otherwise. +template +bool FindCopy(const Collection& collection, + const Key& key, + Value* const value) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return false; + } + if (value) { + *value = it->second; + } + return true; +} + +// +// Contains*() +// + +// Returns true if and only if the given collection contains the given key. +template +bool ContainsKey(const Collection& collection, const Key& key) { + return collection.find(key) != collection.end(); +} + +// Returns true if and only if the given collection contains the given key-value +// pair. +template +bool ContainsKeyValuePair(const Collection& collection, + const Key& key, + const Value& value) { + typedef typename Collection::const_iterator const_iterator; + std::pair range = collection.equal_range(key); + for (const_iterator it = range.first; it != range.second; ++it) { + if (it->second == value) { + return true; + } + } + return false; +} + +// +// Insert*() +// + +// Inserts the given key-value pair into the collection. Returns true if and +// only if the key from the given pair didn't previously exist. Otherwise, the +// value in the map is replaced with the value from the given pair. +template +bool InsertOrUpdate(Collection* const collection, + const typename Collection::value_type& vt) { + std::pair ret = collection->insert(vt); + if (!ret.second) { + // update + ret.first->second = vt.second; + return false; + } + return true; +} + +// Same as above, except that the key and value are passed separately. +template +bool InsertOrUpdate(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + return InsertOrUpdate( + collection, typename Collection::value_type(key, value)); +} + +// Inserts/updates all the key-value pairs from the range defined by the +// iterators "first" and "last" into the given collection. +template +void InsertOrUpdateMany(Collection* const collection, + InputIterator first, InputIterator last) { + for (; first != last; ++first) { + InsertOrUpdate(collection, *first); + } +} + +// Change the value associated with a particular key in a map or hash_map +// of the form map which owns the objects pointed to by the +// value pointers. If there was an existing value for the key, it is deleted. +// True indicates an insert took place, false indicates an update + delete. +template +bool InsertAndDeleteExisting( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + std::pair ret = + collection->insert(typename Collection::value_type(key, value)); + if (!ret.second) { + delete ret.first->second; + ret.first->second = value; + return false; + } + return true; +} + +// Inserts the given key and value into the given collection if and only if the +// given key did NOT already exist in the collection. If the key previously +// existed in the collection, the value is not changed. Returns true if the +// key-value pair was inserted; returns false if the key was already present. +template +bool InsertIfNotPresent(Collection* const collection, + const typename Collection::value_type& vt) { + return collection->insert(vt).second; +} + +// Same as above except the key and value are passed separately. +template +bool InsertIfNotPresent( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + return InsertIfNotPresent( + collection, typename Collection::value_type(key, value)); +} + +// Same as above except dies if the key already exists in the collection. +template +void InsertOrDie(Collection* const collection, + const typename Collection::value_type& value) { + CHECK(InsertIfNotPresent(collection, value)) << "duplicate value: " << value; +} + +// Same as above except doesn't log the value on error. +template +void InsertOrDieNoPrint(Collection* const collection, + const typename Collection::value_type& value) { + CHECK(InsertIfNotPresent(collection, value)) << "duplicate value."; +} + +// Inserts the key-value pair into the collection. Dies if key was already +// present. +template +void InsertOrDie(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& data) { + typedef typename Collection::value_type value_type; + GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) + << "duplicate key: " << key; +} + +// Same as above except doesn't log the key on error. +template +void InsertOrDieNoPrint( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& data) { + typedef typename Collection::value_type value_type; + GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key."; +} + +// Inserts a new key and default-initialized value. Dies if the key was already +// present. Returns a reference to the value. Example usage: +// +// map m; +// SomeProto& proto = InsertKeyOrDie(&m, 3); +// proto.set_field("foo"); +template +typename Collection::value_type::second_type& InsertKeyOrDie( + Collection* const collection, + const typename Collection::value_type::first_type& key) { + typedef typename Collection::value_type value_type; + std::pair res = + collection->insert(value_type(key, typename value_type::second_type())); + GOOGLE_CHECK(res.second) << "duplicate key: " << key; + return res.first->second; +} + +// +// Lookup*() +// + +// Looks up a given key and value pair in a collection and inserts the key-value +// pair if it's not already present. Returns a reference to the value associated +// with the key. +template +typename Collection::value_type::second_type& +LookupOrInsert(Collection* const collection, + const typename Collection::value_type& vt) { + return collection->insert(vt).first->second; +} + +// Same as above except the key-value are passed separately. +template +typename Collection::value_type::second_type& +LookupOrInsert(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + return LookupOrInsert( + collection, typename Collection::value_type(key, value)); +} + +// Counts the number of equivalent elements in the given "sequence", and stores +// the results in "count_map" with element as the key and count as the value. +// +// Example: +// vector v = {"a", "b", "c", "a", "b"}; +// map m; +// AddTokenCounts(v, 1, &m); +// assert(m["a"] == 2); +// assert(m["b"] == 2); +// assert(m["c"] == 1); +template +void AddTokenCounts( + const Sequence& sequence, + const typename Collection::value_type::second_type& increment, + Collection* const count_map) { + for (typename Sequence::const_iterator it = sequence.begin(); + it != sequence.end(); ++it) { + typename Collection::value_type::second_type& value = + LookupOrInsert(count_map, *it, + typename Collection::value_type::second_type()); + value += increment; + } +} + +// Returns a reference to the value associated with key. If not found, a value +// is default constructed on the heap and added to the map. +// +// This function is useful for containers of the form map, where +// inserting a new key, value pair involves constructing a new heap-allocated +// Value, and storing a pointer to that in the collection. +template +typename Collection::value_type::second_type& +LookupOrInsertNew(Collection* const collection, + const typename Collection::value_type::first_type& key) { + typedef typename std::iterator_traits< + typename Collection::value_type::second_type>::value_type Element; + std::pair ret = + collection->insert(typename Collection::value_type( + key, + static_cast(NULL))); + if (ret.second) { + ret.first->second = new Element(); + } + return ret.first->second; +} + +// Same as above but constructs the value using the single-argument constructor +// and the given "arg". +template +typename Collection::value_type::second_type& +LookupOrInsertNew(Collection* const collection, + const typename Collection::value_type::first_type& key, + const Arg& arg) { + typedef typename std::iterator_traits< + typename Collection::value_type::second_type>::value_type Element; + std::pair ret = + collection->insert(typename Collection::value_type( + key, + static_cast(NULL))); + if (ret.second) { + ret.first->second = new Element(arg); + } + return ret.first->second; +} + +// Lookup of linked/shared pointers is used in two scenarios: +// +// Use LookupOrInsertNewLinkedPtr if the container owns the elements. +// In this case it is fine working with the raw pointer as long as it is +// guaranteed that no other thread can delete/update an accessed element. +// A mutex will need to lock the container operation as well as the use +// of the returned elements. Finding an element may be performed using +// FindLinkedPtr*(). +// +// Use LookupOrInsertNewSharedPtr if the container does not own the elements +// for their whole lifetime. This is typically the case when a reader allows +// parallel updates to the container. In this case a Mutex only needs to lock +// container operations, but all element operations must be performed on the +// shared pointer. Finding an element must be performed using FindPtr*() and +// cannot be done with FindLinkedPtr*() even though it compiles. + +// Lookup a key in a map or hash_map whose values are linked_ptrs. If it is +// missing, set collection[key].reset(new Value::element_type) and return that. +// Value::element_type must be default constructable. +template +typename Collection::value_type::second_type::element_type* +LookupOrInsertNewLinkedPtr( + Collection* const collection, + const typename Collection::value_type::first_type& key) { + typedef typename Collection::value_type::second_type Value; + std::pair ret = + collection->insert(typename Collection::value_type(key, Value())); + if (ret.second) { + ret.first->second.reset(new typename Value::element_type); + } + return ret.first->second.get(); +} + +// A variant of LookupOrInsertNewLinkedPtr where the value is constructed using +// a single-parameter constructor. Note: the constructor argument is computed +// even if it will not be used, so only values cheap to compute should be passed +// here. On the other hand it does not matter how expensive the construction of +// the actual stored value is, as that only occurs if necessary. +template +typename Collection::value_type::second_type::element_type* +LookupOrInsertNewLinkedPtr( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const Arg& arg) { + typedef typename Collection::value_type::second_type Value; + std::pair ret = + collection->insert(typename Collection::value_type(key, Value())); + if (ret.second) { + ret.first->second.reset(new typename Value::element_type(arg)); + } + return ret.first->second.get(); +} + +// Lookup a key in a map or hash_map whose values are shared_ptrs. If it is +// missing, set collection[key].reset(new Value::element_type). Unlike +// LookupOrInsertNewLinkedPtr, this function returns the shared_ptr instead of +// the raw pointer. Value::element_type must be default constructable. +template +typename Collection::value_type::second_type& +LookupOrInsertNewSharedPtr( + Collection* const collection, + const typename Collection::value_type::first_type& key) { + typedef typename Collection::value_type::second_type SharedPtr; + typedef typename Collection::value_type::second_type::element_type Element; + std::pair ret = + collection->insert(typename Collection::value_type(key, SharedPtr())); + if (ret.second) { + ret.first->second.reset(new Element()); + } + return ret.first->second; +} + +// A variant of LookupOrInsertNewSharedPtr where the value is constructed using +// a single-parameter constructor. Note: the constructor argument is computed +// even if it will not be used, so only values cheap to compute should be passed +// here. On the other hand it does not matter how expensive the construction of +// the actual stored value is, as that only occurs if necessary. +template +typename Collection::value_type::second_type& +LookupOrInsertNewSharedPtr( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const Arg& arg) { + typedef typename Collection::value_type::second_type SharedPtr; + typedef typename Collection::value_type::second_type::element_type Element; + std::pair ret = + collection->insert(typename Collection::value_type(key, SharedPtr())); + if (ret.second) { + ret.first->second.reset(new Element(arg)); + } + return ret.first->second; +} + +// +// Misc Utility Functions +// + +// Updates the value associated with the given key. If the key was not already +// present, then the key-value pair are inserted and "previous" is unchanged. If +// the key was already present, the value is updated and "*previous" will +// contain a copy of the old value. +// +// InsertOrReturnExisting has complementary behavior that returns the +// address of an already existing value, rather than updating it. +template +bool UpdateReturnCopy(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value, + typename Collection::value_type::second_type* previous) { + std::pair ret = + collection->insert(typename Collection::value_type(key, value)); + if (!ret.second) { + // update + if (previous) { + *previous = ret.first->second; + } + ret.first->second = value; + return true; + } + return false; +} + +// Same as above except that the key and value are passed as a pair. +template +bool UpdateReturnCopy(Collection* const collection, + const typename Collection::value_type& vt, + typename Collection::value_type::second_type* previous) { + std::pair ret = collection->insert(vt); + if (!ret.second) { + // update + if (previous) { + *previous = ret.first->second; + } + ret.first->second = vt.second; + return true; + } + return false; +} + +// Tries to insert the given key-value pair into the collection. Returns NULL if +// the insert succeeds. Otherwise, returns a pointer to the existing value. +// +// This complements UpdateReturnCopy in that it allows to update only after +// verifying the old value and still insert quickly without having to look up +// twice. Unlike UpdateReturnCopy this also does not come with the issue of an +// undefined previous* in case new data was inserted. +template +typename Collection::value_type::second_type* const +InsertOrReturnExisting(Collection* const collection, + const typename Collection::value_type& vt) { + std::pair ret = collection->insert(vt); + if (ret.second) { + return NULL; // Inserted, no existing previous value. + } else { + return &ret.first->second; // Return address of already existing value. + } +} + +// Same as above, except for explicit key and data. +template +typename Collection::value_type::second_type* const +InsertOrReturnExisting( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& data) { + return InsertOrReturnExisting(collection, + typename Collection::value_type(key, data)); +} + +// Erases the collection item identified by the given key, and returns the value +// associated with that key. It is assumed that the value (i.e., the +// mapped_type) is a pointer. Returns NULL if the key was not found in the +// collection. +// +// Examples: +// map my_map; +// +// One line cleanup: +// delete EraseKeyReturnValuePtr(&my_map, "abc"); +// +// Use returned value: +// scoped_ptr value_ptr(EraseKeyReturnValuePtr(&my_map, "abc")); +// if (value_ptr.get()) +// value_ptr->DoSomething(); +// +template +typename Collection::value_type::second_type EraseKeyReturnValuePtr( + Collection* const collection, + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection->find(key); + if (it == collection->end()) { + return NULL; + } + typename Collection::value_type::second_type v = it->second; + collection->erase(it); + return v; +} + +// Inserts all the keys from map_container into key_container, which must +// support insert(MapContainer::key_type). +// +// Note: any initial contents of the key_container are not cleared. +template +void InsertKeysFromMap(const MapContainer& map_container, + KeyContainer* key_container) { + GOOGLE_CHECK(key_container != NULL); + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + key_container->insert(it->first); + } +} + +// Appends all the keys from map_container into key_container, which must +// support push_back(MapContainer::key_type). +// +// Note: any initial contents of the key_container are not cleared. +template +void AppendKeysFromMap(const MapContainer& map_container, + KeyContainer* key_container) { + GOOGLE_CHECK(key_container != NULL); + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + key_container->push_back(it->first); + } +} + +// A more specialized overload of AppendKeysFromMap to optimize reallocations +// for the common case in which we're appending keys to a vector and hence can +// (and sometimes should) call reserve() first. +// +// (It would be possible to play SFINAE games to call reserve() for any +// container that supports it, but this seems to get us 99% of what we need +// without the complexity of a SFINAE-based solution.) +template +void AppendKeysFromMap(const MapContainer& map_container, + vector* key_container) { + GOOGLE_CHECK(key_container != NULL); + // We now have the opportunity to call reserve(). Calling reserve() every + // time is a bad idea for some use cases: libstdc++'s implementation of + // vector<>::reserve() resizes the vector's backing store to exactly the + // given size (unless it's already at least that big). Because of this, + // the use case that involves appending a lot of small maps (total size + // N) one by one to a vector would be O(N^2). But never calling reserve() + // loses the opportunity to improve the use case of adding from a large + // map to an empty vector (this improves performance by up to 33%). A + // number of heuristics are possible; see the discussion in + // cl/34081696. Here we use the simplest one. + if (key_container->empty()) { + key_container->reserve(map_container.size()); + } + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + key_container->push_back(it->first); + } +} + +// Inserts all the values from map_container into value_container, which must +// support push_back(MapContainer::mapped_type). +// +// Note: any initial contents of the value_container are not cleared. +template +void AppendValuesFromMap(const MapContainer& map_container, + ValueContainer* value_container) { + GOOGLE_CHECK(value_container != NULL); + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + value_container->push_back(it->second); + } +} + +// A more specialized overload of AppendValuesFromMap to optimize reallocations +// for the common case in which we're appending values to a vector and hence +// can (and sometimes should) call reserve() first. +// +// (It would be possible to play SFINAE games to call reserve() for any +// container that supports it, but this seems to get us 99% of what we need +// without the complexity of a SFINAE-based solution.) +template +void AppendValuesFromMap(const MapContainer& map_container, + vector* value_container) { + GOOGLE_CHECK(value_container != NULL); + // See AppendKeysFromMap for why this is done. + if (value_container->empty()) { + value_container->reserve(map_container.size()); + } + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + value_container->push_back(it->second); + } +} + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ diff --git a/src/google/protobuf/stubs/once.cc b/src/google/protobuf/stubs/once.cc index 5b7af9c..1e24b85 100644 --- a/src/google/protobuf/stubs/once.cc +++ b/src/google/protobuf/stubs/once.cc @@ -35,54 +35,65 @@ // This header is intended to be included only by internal .cc files and // generated .pb.cc files. Users should not use this directly. +#include + +#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY + #ifdef _WIN32 #include +#else +#include #endif -#include +#include namespace google { namespace protobuf { -#ifdef _WIN32 - -struct ProtobufOnceInternal { - ProtobufOnceInternal() { - InitializeCriticalSection(&critical_section); - } - ~ProtobufOnceInternal() { - DeleteCriticalSection(&critical_section); - } - CRITICAL_SECTION critical_section; -}; - -ProtobufOnceType::~ProtobufOnceType() -{ - delete internal_; - internal_ = NULL; -} +namespace { -ProtobufOnceType::ProtobufOnceType() { - // internal_ may be non-NULL if Init() was already called. - if (internal_ == NULL) internal_ = new ProtobufOnceInternal; +void SchedYield() { +#ifdef _WIN32 + Sleep(0); +#else // POSIX + sched_yield(); +#endif } -void ProtobufOnceType::Init(void (*init_func)()) { - // internal_ may be NULL if we're still in dynamic initialization and the - // constructor has not been called yet. As mentioned in once.h, we assume - // that the program is still single-threaded at this time, and therefore it - // should be safe to initialize internal_ like so. - if (internal_ == NULL) internal_ = new ProtobufOnceInternal; +} // namespace - EnterCriticalSection(&internal_->critical_section); - if (!initialized_) { - init_func(); - initialized_ = true; +void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure) { + internal::AtomicWord state = internal::Acquire_Load(once); + // Fast path. The provided closure was already executed. + if (state == ONCE_STATE_DONE) { + return; + } + // The closure execution did not complete yet. The once object can be in one + // of the two following states: + // - UNINITIALIZED: We are the first thread calling this function. + // - EXECUTING_CLOSURE: Another thread is already executing the closure. + // + // First, try to change the state from UNINITIALIZED to EXECUTING_CLOSURE + // atomically. + state = internal::Acquire_CompareAndSwap( + once, ONCE_STATE_UNINITIALIZED, ONCE_STATE_EXECUTING_CLOSURE); + if (state == ONCE_STATE_UNINITIALIZED) { + // We are the first thread to call this function, so we have to call the + // closure. + closure->Run(); + internal::Release_Store(once, ONCE_STATE_DONE); + } else { + // Another thread has already started executing the closure. We need to + // wait until it completes the initialization. + while (state == ONCE_STATE_EXECUTING_CLOSURE) { + // Note that futex() could be used here on Linux as an improvement. + SchedYield(); + state = internal::Acquire_Load(once); + } } - LeaveCriticalSection(&internal_->critical_section); } -#endif - } // namespace protobuf } // namespace google + +#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY diff --git a/src/google/protobuf/stubs/once.h b/src/google/protobuf/stubs/once.h index 0dee407..86a4c01 100644 --- a/src/google/protobuf/stubs/once.h +++ b/src/google/protobuf/stubs/once.h @@ -37,16 +37,22 @@ // // This is basically a portable version of pthread_once(). // -// This header declares three things: +// This header declares: // * A type called ProtobufOnceType. // * A macro GOOGLE_PROTOBUF_DECLARE_ONCE() which declares a variable of type // ProtobufOnceType. This is the only legal way to declare such a variable. -// The macro may only be used at the global scope (you cannot create local -// or class member variables of this type). -// * A function GogoleOnceInit(ProtobufOnceType* once, void (*init_func)()). +// The macro may only be used at the global scope (you cannot create local or +// class member variables of this type). +// * A function GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()). // This function, when invoked multiple times given the same ProtobufOnceType // object, will invoke init_func on the first call only, and will make sure // none of the calls return before that first call to init_func has finished. +// * The user can provide a parameter which GoogleOnceInit() forwards to the +// user-provided function when it is called. Usage example: +// int a = 10; +// GoogleOnceInit(&my_once, &MyFunctionExpectingIntArgument, &a); +// * This implementation guarantees that ProtobufOnceType is a POD (i.e. no +// static initializer generated). // // This implements a way to perform lazy initialization. It's more efficient // than using mutexes as no lock is needed if initialization has already @@ -72,50 +78,87 @@ #ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__ #define GOOGLE_PROTOBUF_STUBS_ONCE_H__ +#include #include -#ifndef _WIN32 -#include -#endif - namespace google { namespace protobuf { -#ifdef _WIN32 - -struct ProtobufOnceInternal; +#ifdef GOOGLE_PROTOBUF_NO_THREAD_SAFETY -struct LIBPROTOBUF_EXPORT ProtobufOnceType { - ProtobufOnceType(); - ~ProtobufOnceType(); - void Init(void (*init_func)()); +typedef bool ProtobufOnceType; - volatile bool initialized_; - ProtobufOnceInternal* internal_; -}; - -#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \ - ::google::protobuf::ProtobufOnceType NAME +#define GOOGLE_PROTOBUF_ONCE_INIT false inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) { - // Note: Double-checked locking is safe on x86. - if (!once->initialized_) { - once->Init(init_func); + if (!*once) { + *once = true; + init_func(); + } +} + +template +inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg), + Arg arg) { + if (!*once) { + *once = true; + init_func(arg); } } #else -typedef pthread_once_t ProtobufOnceType; +enum { + ONCE_STATE_UNINITIALIZED = 0, + ONCE_STATE_EXECUTING_CLOSURE = 1, + ONCE_STATE_DONE = 2 +}; + +typedef internal::AtomicWord ProtobufOnceType; -#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \ - pthread_once_t NAME = PTHREAD_ONCE_INIT +#define GOOGLE_PROTOBUF_ONCE_INIT ::google::protobuf::ONCE_STATE_UNINITIALIZED + +LIBPROTOBUF_EXPORT +void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure); inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) { - pthread_once(once, init_func); + if (internal::Acquire_Load(once) != ONCE_STATE_DONE) { + internal::FunctionClosure0 func(init_func, false); + GoogleOnceInitImpl(once, &func); + } +} + +template +inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg*), + Arg* arg) { + if (internal::Acquire_Load(once) != ONCE_STATE_DONE) { + internal::FunctionClosure1 func(init_func, false, arg); + GoogleOnceInitImpl(once, &func); + } } -#endif +#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY + +class GoogleOnceDynamic { + public: + GoogleOnceDynamic() : state_(GOOGLE_PROTOBUF_ONCE_INIT) { } + + // If this->Init() has not been called before by any thread, + // execute (*func_with_arg)(arg) then return. + // Otherwise, wait until that prior invocation has finished + // executing its function, then return. + template + void Init(void (*func_with_arg)(T*), T* arg) { + GoogleOnceInit(&this->state_, + func_with_arg, + arg); + } + private: + ProtobufOnceType state_; +}; + +#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \ + ::google::protobuf::ProtobufOnceType NAME = GOOGLE_PROTOBUF_ONCE_INIT } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h new file mode 100644 index 0000000..1705b41 --- /dev/null +++ b/src/google/protobuf/stubs/platform_macros.h @@ -0,0 +1,86 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +#ifndef GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ +#define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ + +#include + +// Processor architecture detection. For more info on what's defined, see: +// http://msdn.microsoft.com/en-us/library/b0084kay.aspx +// http://www.agner.org/optimize/calling_conventions.pdf +// or with gcc, run: "echo | gcc -E -dM -" +#if defined(_M_X64) || defined(__x86_64__) +#define GOOGLE_PROTOBUF_ARCH_X64 1 +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +#elif defined(_M_IX86) || defined(__i386__) +#define GOOGLE_PROTOBUF_ARCH_IA32 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(__QNX__) +#define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(__ARMEL__) +#define GOOGLE_PROTOBUF_ARCH_ARM 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(__aarch64__) +#define GOOGLE_PROTOBUF_ARCH_AARCH64 1 +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +#elif defined(__MIPSEL__) +#if defined(__LP64__) +#define GOOGLE_PROTOBUF_ARCH_MIPS64 1 +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +#else +#define GOOGLE_PROTOBUF_ARCH_MIPS 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#endif +#elif defined(__pnacl__) +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(__ppc__) +#define GOOGLE_PROTOBUF_ARCH_PPC 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(__GNUC__) && \ + (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)) +// We fallback to the generic GCC >= 4.7 implementation in atomicops.h +# if __LP64__ +# define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +# else +# define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +# endif +#else +#error Host architecture was not detected as supported by protobuf +#endif + +#if defined(__APPLE__) +#define GOOGLE_PROTOBUF_OS_APPLE +#elif defined(__native_client__) +#define GOOGLE_PROTOBUF_OS_NACL +#endif + +#endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ diff --git a/src/google/protobuf/stubs/shared_ptr.h b/src/google/protobuf/stubs/shared_ptr.h new file mode 100644 index 0000000..c659307 --- /dev/null +++ b/src/google/protobuf/stubs/shared_ptr.h @@ -0,0 +1,470 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// from google3/util/gtl/shared_ptr.h + +#ifndef GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__ +#define GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__ + +#include + +#include // for swap +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +// Alias to std::shared_ptr for any C++11 platform, +// and for any supported MSVC compiler. +#if !defined(UTIL_GTL_USE_STD_SHARED_PTR) && \ + (defined(COMPILER_MSVC) || defined(LANG_CXX11)) +#define UTIL_GTL_USE_STD_SHARED_PTR 1 +#endif + +#if defined(UTIL_GTL_USE_STD_SHARED_PTR) && UTIL_GTL_USE_STD_SHARED_PTR + +// These are transitional. They will be going away soon. +// Please just #include and just type std::shared_ptr yourself, instead +// of relying on this file. +// +// Migration doc: http://go/std-shared-ptr-lsc +using std::enable_shared_from_this; +using std::shared_ptr; +using std::static_pointer_cast; +using std::weak_ptr; + +#else // below, UTIL_GTL_USE_STD_SHARED_PTR not set or set to 0. + +// For everything else there is the google3 implementation. +inline bool RefCountDec(volatile Atomic32 *ptr) { + return Barrier_AtomicIncrement(ptr, -1) != 0; +} + +inline void RefCountInc(volatile Atomic32 *ptr) { + NoBarrier_AtomicIncrement(ptr, 1); +} + +template class shared_ptr; +template class weak_ptr; + +// This class is an internal implementation detail for shared_ptr. If two +// shared_ptrs point to the same object, they also share a control block. +// An "empty" shared_pointer refers to NULL and also has a NULL control block. +// It contains all of the state that's needed for reference counting or any +// other kind of resource management. In this implementation the control block +// happens to consist of two atomic words, the reference count (the number +// of shared_ptrs that share ownership of the object) and the weak count +// (the number of weak_ptrs that observe the object, plus 1 if the +// refcount is nonzero). +// +// The "plus 1" is to prevent a race condition in the shared_ptr and +// weak_ptr destructors. We need to make sure the control block is +// only deleted once, so we need to make sure that at most one +// object sees the weak count decremented from 1 to 0. +class SharedPtrControlBlock { + template friend class shared_ptr; + template friend class weak_ptr; + private: + SharedPtrControlBlock() : refcount_(1), weak_count_(1) { } + Atomic32 refcount_; + Atomic32 weak_count_; +}; + +// Forward declaration. The class is defined below. +template class enable_shared_from_this; + +template +class shared_ptr { + template friend class weak_ptr; + public: + typedef T element_type; + + shared_ptr() : ptr_(NULL), control_block_(NULL) {} + + explicit shared_ptr(T* ptr) + : ptr_(ptr), + control_block_(ptr != NULL ? new SharedPtrControlBlock : NULL) { + // If p is non-null and T inherits from enable_shared_from_this, we + // set up the data that shared_from_this needs. + MaybeSetupWeakThis(ptr); + } + + // Copy constructor: makes this object a copy of ptr, and increments + // the reference count. + template + shared_ptr(const shared_ptr& ptr) + : ptr_(NULL), + control_block_(NULL) { + Initialize(ptr); + } + // Need non-templated version to prevent the compiler-generated default + shared_ptr(const shared_ptr& ptr) + : ptr_(NULL), + control_block_(NULL) { + Initialize(ptr); + } + + // Assignment operator. Replaces the existing shared_ptr with ptr. + // Increment ptr's reference count and decrement the one being replaced. + template + shared_ptr& operator=(const shared_ptr& ptr) { + if (ptr_ != ptr.ptr_) { + shared_ptr me(ptr); // will hold our previous state to be destroyed. + swap(me); + } + return *this; + } + + // Need non-templated version to prevent the compiler-generated default + shared_ptr& operator=(const shared_ptr& ptr) { + if (ptr_ != ptr.ptr_) { + shared_ptr me(ptr); // will hold our previous state to be destroyed. + swap(me); + } + return *this; + } + + // TODO(austern): Consider providing this constructor. The draft C++ standard + // (20.8.10.2.1) includes it. However, it says that this constructor throws + // a bad_weak_ptr exception when ptr is expired. Is it better to provide this + // constructor and make it do something else, like fail with a CHECK, or to + // leave this constructor out entirely? + // + // template + // shared_ptr(const weak_ptr& ptr); + + ~shared_ptr() { + if (ptr_ != NULL) { + if (!RefCountDec(&control_block_->refcount_)) { + delete ptr_; + + // weak_count_ is defined as the number of weak_ptrs that observe + // ptr_, plus 1 if refcount_ is nonzero. + if (!RefCountDec(&control_block_->weak_count_)) { + delete control_block_; + } + } + } + } + + // Replaces underlying raw pointer with the one passed in. The reference + // count is set to one (or zero if the pointer is NULL) for the pointer + // being passed in and decremented for the one being replaced. + // + // If you have a compilation error with this code, make sure you aren't + // passing NULL, nullptr, or 0 to this function. Call reset without an + // argument to reset to a null ptr. + template + void reset(Y* p) { + if (p != ptr_) { + shared_ptr tmp(p); + tmp.swap(*this); + } + } + + void reset() { + reset(static_cast(NULL)); + } + + // Exchanges the contents of this with the contents of r. This function + // supports more efficient swapping since it eliminates the need for a + // temporary shared_ptr object. + void swap(shared_ptr& r) { + using std::swap; // http://go/using-std-swap + swap(ptr_, r.ptr_); + swap(control_block_, r.control_block_); + } + + // The following function is useful for gaining access to the underlying + // pointer when a shared_ptr remains in scope so the reference-count is + // known to be > 0 (e.g. for parameter passing). + T* get() const { + return ptr_; + } + + T& operator*() const { + return *ptr_; + } + + T* operator->() const { + return ptr_; + } + + long use_count() const { + return control_block_ ? control_block_->refcount_ : 1; + } + + bool unique() const { + return use_count() == 1; + } + + private: + // If r is non-empty, initialize *this to share ownership with r, + // increasing the underlying reference count. + // If r is empty, *this remains empty. + // Requires: this is empty, namely this->ptr_ == NULL. + template + void Initialize(const shared_ptr& r) { + // This performs a static_cast on r.ptr_ to U*, which is a no-op since it + // is already a U*. So initialization here requires that r.ptr_ is + // implicitly convertible to T*. + InitializeWithStaticCast(r); + } + + // Initializes *this as described in Initialize, but additionally performs a + // static_cast from r.ptr_ (V*) to U*. + // NOTE(gfc): We'd need a more general form to support const_pointer_cast and + // dynamic_pointer_cast, but those operations are sufficiently discouraged + // that supporting static_pointer_cast is sufficient. + template + void InitializeWithStaticCast(const shared_ptr& r) { + if (r.control_block_ != NULL) { + RefCountInc(&r.control_block_->refcount_); + + ptr_ = static_cast(r.ptr_); + control_block_ = r.control_block_; + } + } + + // Helper function for the constructor that takes a raw pointer. If T + // doesn't inherit from enable_shared_from_this then we have nothing to + // do, so this function is trivial and inline. The other version is declared + // out of line, after the class definition of enable_shared_from_this. + void MaybeSetupWeakThis(enable_shared_from_this* ptr); + void MaybeSetupWeakThis(...) { } + + T* ptr_; + SharedPtrControlBlock* control_block_; + +#ifndef SWIG + template + friend class shared_ptr; + + template + friend shared_ptr static_pointer_cast(const shared_ptr& rhs); +#endif +}; + +// Matches the interface of std::swap as an aid to generic programming. +template void swap(shared_ptr& r, shared_ptr& s) { + r.swap(s); +} + +template +shared_ptr static_pointer_cast(const shared_ptr& rhs) { + shared_ptr lhs; + lhs.template InitializeWithStaticCast(rhs); + return lhs; +} + +// See comments at the top of the file for a description of why this +// class exists, and the draft C++ standard (as of July 2009 the +// latest draft is N2914) for the detailed specification. +template +class weak_ptr { + template friend class weak_ptr; + public: + typedef T element_type; + + // Create an empty (i.e. already expired) weak_ptr. + weak_ptr() : ptr_(NULL), control_block_(NULL) { } + + // Create a weak_ptr that observes the same object that ptr points + // to. Note that there is no race condition here: we know that the + // control block can't disappear while we're looking at it because + // it is owned by at least one shared_ptr, ptr. + template weak_ptr(const shared_ptr& ptr) { + CopyFrom(ptr.ptr_, ptr.control_block_); + } + + // Copy a weak_ptr. The object it points to might disappear, but we + // don't care: we're only working with the control block, and it can't + // disappear while we're looking at because it's owned by at least one + // weak_ptr, ptr. + template weak_ptr(const weak_ptr& ptr) { + CopyFrom(ptr.ptr_, ptr.control_block_); + } + + // Need non-templated version to prevent default copy constructor + weak_ptr(const weak_ptr& ptr) { + CopyFrom(ptr.ptr_, ptr.control_block_); + } + + // Destroy the weak_ptr. If no shared_ptr owns the control block, and if + // we are the last weak_ptr to own it, then it can be deleted. Note that + // weak_count_ is defined as the number of weak_ptrs sharing this control + // block, plus 1 if there are any shared_ptrs. We therefore know that it's + // safe to delete the control block when weak_count_ reaches 0, without + // having to perform any additional tests. + ~weak_ptr() { + if (control_block_ != NULL && + !RefCountDec(&control_block_->weak_count_)) { + delete control_block_; + } + } + + weak_ptr& operator=(const weak_ptr& ptr) { + if (&ptr != this) { + weak_ptr tmp(ptr); + tmp.swap(*this); + } + return *this; + } + template weak_ptr& operator=(const weak_ptr& ptr) { + weak_ptr tmp(ptr); + tmp.swap(*this); + return *this; + } + template weak_ptr& operator=(const shared_ptr& ptr) { + weak_ptr tmp(ptr); + tmp.swap(*this); + return *this; + } + + void swap(weak_ptr& ptr) { + using std::swap; // http://go/using-std-swap + swap(ptr_, ptr.ptr_); + swap(control_block_, ptr.control_block_); + } + + void reset() { + weak_ptr tmp; + tmp.swap(*this); + } + + // Return the number of shared_ptrs that own the object we are observing. + // Note that this number can be 0 (if this pointer has expired). + long use_count() const { + return control_block_ != NULL ? control_block_->refcount_ : 0; + } + + bool expired() const { return use_count() == 0; } + + // Return a shared_ptr that owns the object we are observing. If we + // have expired, the shared_ptr will be empty. We have to be careful + // about concurrency, though, since some other thread might be + // destroying the last owning shared_ptr while we're in this + // function. We want to increment the refcount only if it's nonzero + // and get the new value, and we want that whole operation to be + // atomic. + shared_ptr lock() const { + shared_ptr result; + if (control_block_ != NULL) { + Atomic32 old_refcount; + do { + old_refcount = control_block_->refcount_; + if (old_refcount == 0) + break; + } while (old_refcount != + NoBarrier_CompareAndSwap( + &control_block_->refcount_, old_refcount, + old_refcount + 1)); + if (old_refcount > 0) { + result.ptr_ = ptr_; + result.control_block_ = control_block_; + } + } + + return result; + } + + private: + void CopyFrom(T* ptr, SharedPtrControlBlock* control_block) { + ptr_ = ptr; + control_block_ = control_block; + if (control_block_ != NULL) + RefCountInc(&control_block_->weak_count_); + } + + private: + element_type* ptr_; + SharedPtrControlBlock* control_block_; +}; + +template void swap(weak_ptr& r, weak_ptr& s) { + r.swap(s); +} + +// See comments at the top of the file for a description of why this class +// exists, and section 20.8.10.5 of the draft C++ standard (as of July 2009 +// the latest draft is N2914) for the detailed specification. +template +class enable_shared_from_this { + friend class shared_ptr; + public: + // Precondition: there must be a shared_ptr that owns *this and that was + // created, directly or indirectly, from a raw pointer of type T*. (The + // latter part of the condition is technical but not quite redundant; it + // rules out some complicated uses involving inheritance hierarchies.) + shared_ptr shared_from_this() { + // Behavior is undefined if the precondition isn't satisfied; we choose + // to die with a CHECK failure. + CHECK(!weak_this_.expired()) << "No shared_ptr owns this object"; + return weak_this_.lock(); + } + shared_ptr shared_from_this() const { + CHECK(!weak_this_.expired()) << "No shared_ptr owns this object"; + return weak_this_.lock(); + } + + protected: + enable_shared_from_this() { } + enable_shared_from_this(const enable_shared_from_this& other) { } + enable_shared_from_this& operator=(const enable_shared_from_this& other) { + return *this; + } + ~enable_shared_from_this() { } + + private: + weak_ptr weak_this_; +}; + +// This is a helper function called by shared_ptr's constructor from a raw +// pointer. If T inherits from enable_shared_from_this, it sets up +// weak_this_ so that shared_from_this works correctly. If T does not inherit +// from weak_this we get a different overload, defined inline, which does +// nothing. +template +void shared_ptr::MaybeSetupWeakThis(enable_shared_from_this* ptr) { + if (ptr) { + CHECK(ptr->weak_this_.expired()) << "Object already owned by a shared_ptr"; + ptr->weak_this_ = *this; + } +} + +#endif // UTIL_GTL_USE_STD_SHARED_PTR + +} // internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__ diff --git a/src/google/protobuf/stubs/stl_util.h b/src/google/protobuf/stubs/stl_util.h new file mode 100644 index 0000000..9021dad --- /dev/null +++ b/src/google/protobuf/stubs/stl_util.h @@ -0,0 +1,121 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// from google3/util/gtl/stl_util.h + +#ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__ +#define GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__ + +#include + +namespace google { +namespace protobuf { + +// STLDeleteContainerPointers() +// For a range within a container of pointers, calls delete +// (non-array version) on these pointers. +// NOTE: for these three functions, we could just implement a DeleteObject +// functor and then call for_each() on the range and functor, but this +// requires us to pull in all of algorithm.h, which seems expensive. +// For hash_[multi]set, it is important that this deletes behind the iterator +// because the hash_set may call the hash function on the iterator when it is +// advanced, which could result in the hash function trying to deference a +// stale pointer. +template +void STLDeleteContainerPointers(ForwardIterator begin, + ForwardIterator end) { + while (begin != end) { + ForwardIterator temp = begin; + ++begin; + delete *temp; + } +} + +// Inside Google, this function implements a horrible, disgusting hack in which +// we reach into the string's private implementation and resize it without +// initializing the new bytes. In some cases doing this can significantly +// improve performance. However, since it's totally non-portable it has no +// place in open source code. Feel free to fill this function in with your +// own disgusting hack if you want the perf boost. +inline void STLStringResizeUninitialized(string* s, size_t new_size) { + s->resize(new_size); +} + +// Return a mutable char* pointing to a string's internal buffer, +// which may not be null-terminated. Writing through this pointer will +// modify the string. +// +// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the +// next call to a string method that invalidates iterators. +// +// As of 2006-04, there is no standard-blessed way of getting a +// mutable reference to a string's internal buffer. However, issue 530 +// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530) +// proposes this as the method. According to Matt Austern, this should +// already work on all current implementations. +inline char* string_as_array(string* str) { + // DO NOT USE const_cast(str->data())! See the unittest for why. + return str->empty() ? NULL : &*str->begin(); +} + +// STLDeleteElements() deletes all the elements in an STL container and clears +// the container. This function is suitable for use with a vector, set, +// hash_set, or any other STL container which defines sensible begin(), end(), +// and clear() methods. +// +// If container is NULL, this function is a no-op. +// +// As an alternative to calling STLDeleteElements() directly, consider +// ElementDeleter (defined below), which ensures that your container's elements +// are deleted when the ElementDeleter goes out of scope. +template +void STLDeleteElements(T *container) { + if (!container) return; + STLDeleteContainerPointers(container->begin(), container->end()); + container->clear(); +} + +// Given an STL container consisting of (key, value) pairs, STLDeleteValues +// deletes all the "value" components and clears the container. Does nothing +// in the case it's given a NULL pointer. + +template +void STLDeleteValues(T *v) { + if (!v) return; + for (typename T::iterator i = v->begin(); i != v->end(); ++i) { + delete i->second; + } + v->clear(); +} + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__ diff --git a/src/google/protobuf/stubs/stringprintf.cc b/src/google/protobuf/stubs/stringprintf.cc new file mode 100644 index 0000000..4a5b858 --- /dev/null +++ b/src/google/protobuf/stubs/stringprintf.cc @@ -0,0 +1,175 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// from google3/base/stringprintf.cc + +#include + +#include +#include // For va_list and related operations +#include // MSVC requires this for _vsnprintf +#include +#include +#include + +namespace google { +namespace protobuf { + +#ifdef _MSC_VER +enum { IS_COMPILER_MSVC = 1 }; +#ifndef va_copy +// Define va_copy for MSVC. This is a hack, assuming va_list is simply a +// pointer into the stack and is safe to copy. +#define va_copy(dest, src) ((dest) = (src)) +#endif +#else +enum { IS_COMPILER_MSVC = 0 }; +#endif + +void StringAppendV(string* dst, const char* format, va_list ap) { + // First try with a small fixed size buffer + static const int kSpaceLength = 1024; + char space[kSpaceLength]; + + // It's possible for methods that use a va_list to invalidate + // the data in it upon use. The fix is to make a copy + // of the structure before using it and use that copy instead. + va_list backup_ap; + va_copy(backup_ap, ap); + int result = vsnprintf(space, kSpaceLength, format, backup_ap); + va_end(backup_ap); + + if (result < kSpaceLength) { + if (result >= 0) { + // Normal case -- everything fit. + dst->append(space, result); + return; + } + + if (IS_COMPILER_MSVC) { + // Error or MSVC running out of space. MSVC 8.0 and higher + // can be asked about space needed with the special idiom below: + va_copy(backup_ap, ap); + result = vsnprintf(NULL, 0, format, backup_ap); + va_end(backup_ap); + } + + if (result < 0) { + // Just an error. + return; + } + } + + // Increase the buffer size to the size requested by vsnprintf, + // plus one for the closing \0. + int length = result+1; + char* buf = new char[length]; + + // Restore the va_list before we use it again + va_copy(backup_ap, ap); + result = vsnprintf(buf, length, format, backup_ap); + va_end(backup_ap); + + if (result >= 0 && result < length) { + // It fit + dst->append(buf, result); + } + delete[] buf; +} + + +string StringPrintf(const char* format, ...) { + va_list ap; + va_start(ap, format); + string result; + StringAppendV(&result, format, ap); + va_end(ap); + return result; +} + +const string& SStringPrintf(string* dst, const char* format, ...) { + va_list ap; + va_start(ap, format); + dst->clear(); + StringAppendV(dst, format, ap); + va_end(ap); + return *dst; +} + +void StringAppendF(string* dst, const char* format, ...) { + va_list ap; + va_start(ap, format); + StringAppendV(dst, format, ap); + va_end(ap); +} + +// Max arguments supported by StringPrintVector +const int kStringPrintfVectorMaxArgs = 32; + +// An empty block of zero for filler arguments. This is const so that if +// printf tries to write to it (via %n) then the program gets a SIGSEGV +// and we can fix the problem or protect against an attack. +static const char string_printf_empty_block[256] = { '\0' }; + +string StringPrintfVector(const char* format, const vector& v) { + GOOGLE_CHECK_LE(v.size(), kStringPrintfVectorMaxArgs) + << "StringPrintfVector currently only supports up to " + << kStringPrintfVectorMaxArgs << " arguments. " + << "Feel free to add support for more if you need it."; + + // Add filler arguments so that bogus format+args have a harder time + // crashing the program, corrupting the program (%n), + // or displaying random chunks of memory to users. + + const char* cstr[kStringPrintfVectorMaxArgs]; + for (int i = 0; i < v.size(); ++i) { + cstr[i] = v[i].c_str(); + } + for (int i = v.size(); i < GOOGLE_ARRAYSIZE(cstr); ++i) { + cstr[i] = &string_printf_empty_block[0]; + } + + // I do not know any way to pass kStringPrintfVectorMaxArgs arguments, + // or any way to build a va_list by hand, or any API for printf + // that accepts an array of arguments. The best I can do is stick + // this COMPILE_ASSERT right next to the actual statement. + + GOOGLE_COMPILE_ASSERT(kStringPrintfVectorMaxArgs == 32, arg_count_mismatch); + return StringPrintf(format, + cstr[0], cstr[1], cstr[2], cstr[3], cstr[4], + cstr[5], cstr[6], cstr[7], cstr[8], cstr[9], + cstr[10], cstr[11], cstr[12], cstr[13], cstr[14], + cstr[15], cstr[16], cstr[17], cstr[18], cstr[19], + cstr[20], cstr[21], cstr[22], cstr[23], cstr[24], + cstr[25], cstr[26], cstr[27], cstr[28], cstr[29], + cstr[30], cstr[31]); +} +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/stringprintf.h b/src/google/protobuf/stubs/stringprintf.h new file mode 100644 index 0000000..4a03e5f --- /dev/null +++ b/src/google/protobuf/stubs/stringprintf.h @@ -0,0 +1,76 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// from google3/base/stringprintf.h +// +// Printf variants that place their output in a C++ string. +// +// Usage: +// string result = StringPrintf("%d %s\n", 10, "hello"); +// SStringPrintf(&result, "%d %s\n", 10, "hello"); +// StringAppendF(&result, "%d %s\n", 20, "there"); + +#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H +#define GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H + +#include +#include +#include + +#include + +namespace google { +namespace protobuf { + +// Return a C++ string +LIBPROTOBUF_EXPORT extern string StringPrintf(const char* format, ...); + +// Store result into a supplied string and return it +LIBPROTOBUF_EXPORT extern const string& SStringPrintf(string* dst, const char* format, ...); + +// Append result to a supplied string +LIBPROTOBUF_EXPORT extern void StringAppendF(string* dst, const char* format, ...); + +// Lower-level routine that takes a va_list and appends to a specified +// string. All other routines are just convenience wrappers around it. +LIBPROTOBUF_EXPORT extern void StringAppendV(string* dst, const char* format, va_list ap); + +// The max arguments supported by StringPrintfVector +LIBPROTOBUF_EXPORT extern const int kStringPrintfVectorMaxArgs; + +// You can use this version when all your arguments are strings, but +// you don't know how many arguments you'll have at compile time. +// StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs +LIBPROTOBUF_EXPORT extern string StringPrintfVector(const char* format, const vector& v); + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H diff --git a/src/google/protobuf/stubs/stringprintf_unittest.cc b/src/google/protobuf/stubs/stringprintf_unittest.cc new file mode 100644 index 0000000..de5ce59 --- /dev/null +++ b/src/google/protobuf/stubs/stringprintf_unittest.cc @@ -0,0 +1,152 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// from google3/base/stringprintf_unittest.cc + +#include + +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace { + +TEST(StringPrintfTest, Empty) { +#if 0 + // gcc 2.95.3, gcc 4.1.0, and gcc 4.2.2 all warn about this: + // warning: zero-length printf format string. + // so we do not allow them in google3. + EXPECT_EQ("", StringPrintf("")); +#endif + EXPECT_EQ("", StringPrintf("%s", string().c_str())); + EXPECT_EQ("", StringPrintf("%s", "")); +} + +TEST(StringPrintfTest, Misc) { +// MSVC and mingw does not support $ format specifier. +#if !defined(_MSC_VER) && !defined(__MINGW32__) + EXPECT_EQ("123hello w", StringPrintf("%3$d%2$s %1$c", 'w', "hello", 123)); +#endif // !_MSC_VER +} + +TEST(StringAppendFTest, Empty) { + string value("Hello"); + const char* empty = ""; + StringAppendF(&value, "%s", empty); + EXPECT_EQ("Hello", value); +} + +TEST(StringAppendFTest, EmptyString) { + string value("Hello"); + StringAppendF(&value, "%s", ""); + EXPECT_EQ("Hello", value); +} + +TEST(StringAppendFTest, String) { + string value("Hello"); + StringAppendF(&value, " %s", "World"); + EXPECT_EQ("Hello World", value); +} + +TEST(StringAppendFTest, Int) { + string value("Hello"); + StringAppendF(&value, " %d", 123); + EXPECT_EQ("Hello 123", value); +} + +TEST(StringPrintfTest, Multibyte) { + // If we are in multibyte mode and feed invalid multibyte sequence, + // StringPrintf should return an empty string instead of running + // out of memory while trying to determine destination buffer size. + // see b/4194543. + + char* old_locale = setlocale(LC_CTYPE, NULL); + // Push locale with multibyte mode + setlocale(LC_CTYPE, "en_US.utf8"); + + const char kInvalidCodePoint[] = "\375\067s"; + string value = StringPrintf("%.*s", 3, kInvalidCodePoint); + + // In some versions of glibc (e.g. eglibc-2.11.1, aka GRTEv2), snprintf + // returns error given an invalid codepoint. Other versions + // (e.g. eglibc-2.15, aka pre-GRTEv3) emit the codepoint verbatim. + // We test that the output is one of the above. + EXPECT_TRUE(value.empty() || value == kInvalidCodePoint); + + // Repeat with longer string, to make sure that the dynamically + // allocated path in StringAppendV is handled correctly. + int n = 2048; + char* buf = new char[n+1]; + memset(buf, ' ', n-3); + memcpy(buf + n - 3, kInvalidCodePoint, 4); + value = StringPrintf("%.*s", n, buf); + // See GRTEv2 vs. GRTEv3 comment above. + EXPECT_TRUE(value.empty() || value == buf); + delete[] buf; + + setlocale(LC_CTYPE, old_locale); +} + +TEST(StringPrintfTest, NoMultibyte) { + // No multibyte handling, but the string contains funny chars. + char* old_locale = setlocale(LC_CTYPE, NULL); + setlocale(LC_CTYPE, "POSIX"); + string value = StringPrintf("%.*s", 3, "\375\067s"); + setlocale(LC_CTYPE, old_locale); + EXPECT_EQ("\375\067s", value); +} + +TEST(StringPrintfTest, DontOverwriteErrno) { + // Check that errno isn't overwritten unless we're printing + // something significantly larger than what people are normally + // printing in their badly written PLOG() statements. + errno = ECHILD; + string value = StringPrintf("Hello, %s!", "World"); + EXPECT_EQ(ECHILD, errno); +} + +TEST(StringPrintfTest, LargeBuf) { + // Check that the large buffer is handled correctly. + int n = 2048; + char* buf = new char[n+1]; + memset(buf, ' ', n); + buf[n] = 0; + string value = StringPrintf("%s", buf); + EXPECT_EQ(buf, value); + delete[] buf; +} + +} // anonymous namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc index bb658ba..814d1b9 100644 --- a/src/google/protobuf/stubs/strutil.cc +++ b/src/google/protobuf/stubs/strutil.cc @@ -189,6 +189,44 @@ void SplitStringUsing(const string& full, SplitStringToIteratorUsing(full, delim, it); } +// Split a string using a character delimiter. Append the components +// to 'result'. If there are consecutive delimiters, this function +// will return corresponding empty strings. The string is split into +// at most the specified number of pieces greedily. This means that the +// last piece may possibly be split further. To split into as many pieces +// as possible, specify 0 as the number of pieces. +// +// If "full" is the empty string, yields an empty string as the only value. +// +// If "pieces" is negative for some reason, it returns the whole string +// ---------------------------------------------------------------------- +template +static inline +void SplitStringToIteratorAllowEmpty(const StringType& full, + const char* delim, + int pieces, + ITR& result) { + string::size_type begin_index, end_index; + begin_index = 0; + + for (int i = 0; (i < pieces-1) || (pieces == 0); i++) { + end_index = full.find_first_of(delim, begin_index); + if (end_index == string::npos) { + *result++ = full.substr(begin_index); + return; + } + *result++ = full.substr(begin_index, (end_index - begin_index)); + begin_index = end_index + 1; + } + *result++ = full.substr(begin_index); +} + +void SplitStringAllowEmpty(const string& full, const char* delim, + vector* result) { + back_insert_iterator > it(*result); + SplitStringToIteratorAllowEmpty(full, delim, 0, it); +} + // ---------------------------------------------------------------------- // JoinStrings() // This merges a vector of string components with delim inserted @@ -558,6 +596,120 @@ uint32 strtou32_adaptor(const char *nptr, char **endptr, int base) { return static_cast(result); } +inline bool safe_parse_sign(string* text /*inout*/, + bool* negative_ptr /*output*/) { + const char* start = text->data(); + const char* end = start + text->size(); + + // Consume whitespace. + while (start < end && (start[0] == ' ')) { + ++start; + } + while (start < end && (end[-1] == ' ')) { + --end; + } + if (start >= end) { + return false; + } + + // Consume sign. + *negative_ptr = (start[0] == '-'); + if (*negative_ptr || start[0] == '+') { + ++start; + if (start >= end) { + return false; + } + } + *text = text->substr(start - text->data(), end - start); + return true; +} + +inline bool safe_parse_positive_int( + string text, int32* value_p) { + int base = 10; + int32 value = 0; + const int32 vmax = std::numeric_limits::max(); + assert(vmax > 0); + assert(vmax >= base); + const int32 vmax_over_base = vmax / base; + const char* start = text.data(); + const char* end = start + text.size(); + // loop over digits + for (; start < end; ++start) { + unsigned char c = static_cast(start[0]); + int digit = c - '0'; + if (digit >= base || digit < 0) { + *value_p = value; + return false; + } + if (value > vmax_over_base) { + *value_p = vmax; + return false; + } + value *= base; + if (value > vmax - digit) { + *value_p = vmax; + return false; + } + value += digit; + } + *value_p = value; + return true; +} + +inline bool safe_parse_negative_int( + string text, int32* value_p) { + int base = 10; + int32 value = 0; + const int32 vmin = std::numeric_limits::min(); + assert(vmin < 0); + assert(vmin <= 0 - base); + int32 vmin_over_base = vmin / base; + // 2003 c++ standard [expr.mul] + // "... the sign of the remainder is implementation-defined." + // Although (vmin/base)*base + vmin%base is always vmin. + // 2011 c++ standard tightens the spec but we cannot rely on it. + if (vmin % base > 0) { + vmin_over_base += 1; + } + const char* start = text.data(); + const char* end = start + text.size(); + // loop over digits + for (; start < end; ++start) { + unsigned char c = static_cast(start[0]); + int digit = c - '0'; + if (digit >= base || digit < 0) { + *value_p = value; + return false; + } + if (value < vmin_over_base) { + *value_p = vmin; + return false; + } + value *= base; + if (value < vmin + digit) { + *value_p = vmin; + return false; + } + value -= digit; + } + *value_p = value; + return true; +} + +bool safe_int(string text, int32* value_p) { + *value_p = 0; + bool negative; + if (!safe_parse_sign(&text, &negative)) { + return false; + } + if (!negative) { + return safe_parse_positive_int(text, value_p); + } else { + return safe_parse_negative_int(text, value_p); + } +} + // ---------------------------------------------------------------------- // FastIntToBuffer() // FastInt64ToBuffer() @@ -670,7 +822,14 @@ char *InternalFastHexToBuffer(uint64 value, char* buffer, int num_byte) { static const char *hexdigits = "0123456789abcdef"; buffer[num_byte] = '\0'; for (int i = num_byte - 1; i >= 0; i--) { +#ifdef _M_X64 + // MSVC x64 platform has a bug optimizing the uint32(value) in the #else + // block. Given that the uint32 cast was to improve performance on 32-bit + // platforms, we use 64-bit '&' directly. + buffer[i] = hexdigits[value & 0xf]; +#else buffer[i] = hexdigits[uint32(value) & 0xf]; +#endif value >>= 4; } return buffer; @@ -1098,68 +1257,22 @@ char* FloatToBuffer(float value, char* buffer) { return buffer; } -// ---------------------------------------------------------------------- -// NoLocaleStrtod() -// This code will make you cry. -// ---------------------------------------------------------------------- - -// Returns a string identical to *input except that the character pointed to -// by radix_pos (which should be '.') is replaced with the locale-specific -// radix character. -string LocalizeRadix(const char* input, const char* radix_pos) { - // Determine the locale-specific radix character by calling sprintf() to - // print the number 1.5, then stripping off the digits. As far as I can - // tell, this is the only portable, thread-safe way to get the C library - // to divuldge the locale's radix character. No, localeconv() is NOT - // thread-safe. - char temp[16]; - int size = sprintf(temp, "%.1f", 1.5); - GOOGLE_CHECK_EQ(temp[0], '1'); - GOOGLE_CHECK_EQ(temp[size-1], '5'); - GOOGLE_CHECK_LE(size, 6); - - // Now replace the '.' in the input with it. - string result; - result.reserve(strlen(input) + size - 3); - result.append(input, radix_pos); - result.append(temp + 1, size - 2); - result.append(radix_pos + 1); - return result; -} +string ToHex(uint64 num) { + if (num == 0) { + return string("0"); + } -double NoLocaleStrtod(const char* text, char** original_endptr) { - // We cannot simply set the locale to "C" temporarily with setlocale() - // as this is not thread-safe. Instead, we try to parse in the current - // locale first. If parsing stops at a '.' character, then this is a - // pretty good hint that we're actually in some other locale in which - // '.' is not the radix character. - - char* temp_endptr; - double result = strtod(text, &temp_endptr); - if (original_endptr != NULL) *original_endptr = temp_endptr; - if (*temp_endptr != '.') return result; - - // Parsing halted on a '.'. Perhaps we're in a different locale? Let's - // try to replace the '.' with a locale-specific radix character and - // try again. - string localized = LocalizeRadix(text, temp_endptr); - const char* localized_cstr = localized.c_str(); - char* localized_endptr; - result = strtod(localized_cstr, &localized_endptr); - if ((localized_endptr - localized_cstr) > - (temp_endptr - text)) { - // This attempt got further, so replacing the decimal must have helped. - // Update original_endptr to point at the right location. - if (original_endptr != NULL) { - // size_diff is non-zero if the localized radix has multiple bytes. - int size_diff = localized.size() - strlen(text); - // const_cast is necessary to match the strtod() interface. - *original_endptr = const_cast( - text + (localized_endptr - localized_cstr - size_diff)); - } + // Compute hex bytes in reverse order, writing to the back of the + // buffer. + char buf[16]; // No more than 16 hex digits needed. + char* bufptr = buf + 16; + static const char kHexChars[] = "0123456789abcdef"; + while (num != 0) { + *--bufptr = kHexChars[num & 0xf]; + num >>= 4; } - return result; + return string(bufptr, buf + 16 - bufptr); } } // namespace protobuf diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h index 777694b..20cea2d 100644 --- a/src/google/protobuf/stubs/strutil.h +++ b/src/google/protobuf/stubs/strutil.h @@ -126,6 +126,7 @@ LIBPROTOBUF_EXPORT void StripString(string* s, const char* remove, // ---------------------------------------------------------------------- // LowerString() // UpperString() +// ToUpper() // Convert the characters in "s" to lowercase or uppercase. ASCII-only: // these functions intentionally ignore locale because they are applied to // identifiers used in the Protocol Buffer language, not to natural-language @@ -148,6 +149,12 @@ inline void UpperString(string * s) { } } +inline string ToUpper(const string& s) { + string out = s; + UpperString(&out); + return out; +} + // ---------------------------------------------------------------------- // StringReplace() // Give me a string and two patterns "old" and "new", and I replace @@ -168,6 +175,33 @@ LIBPROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub, LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim, vector* res); +// Split a string using one or more byte delimiters, presented +// as a nul-terminated c string. Append the components to 'result'. +// If there are consecutive delimiters, this function will return +// corresponding empty strings. If you want to drop the empty +// strings, try SplitStringUsing(). +// +// If "full" is the empty string, yields an empty string as the only value. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full, + const char* delim, + vector* result); + +// ---------------------------------------------------------------------- +// Split() +// Split a string using a character delimiter. +// ---------------------------------------------------------------------- +inline vector Split( + const string& full, const char* delim, bool skip_empty = true) { + vector result; + if (skip_empty) { + SplitStringUsing(full, delim, &result); + } else { + SplitStringAllowEmpty(full, delim, &result); + } + return result; +} + // ---------------------------------------------------------------------- // JoinStrings() // These methods concatenate a vector of strings into a C++ string, using @@ -207,9 +241,7 @@ inline string JoinStrings(const vector& components, // hex digits, upper or lower case) to specify a Unicode code // point. The dest array will contain the UTF8-encoded version of // that code-point (e.g., if source contains \u2019, then dest will -// contain the three bytes 0xE2, 0x80, and 0x99). For the inverse -// transformation, use UniLib::UTF8EscapeString -// (util/utf8/unilib.h), not CEscapeString. +// contain the three bytes 0xE2, 0x80, and 0x99). // // Errors: In the first form of the call, errors are reported with // LOG(ERROR). The same is true for the second form of the call if @@ -317,6 +349,15 @@ inline uint64 strtou64(const char *nptr, char **endptr, int base) { } // ---------------------------------------------------------------------- +// safe_strto32() +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT bool safe_int(string text, int32* value_p); + +inline bool safe_strto32(string text, int32* value) { + return safe_int(text, value); +} + +// ---------------------------------------------------------------------- // FastIntToBuffer() // FastHexToBuffer() // FastHex64ToBuffer() @@ -444,16 +485,78 @@ static const int kDoubleToBufferSize = 32; static const int kFloatToBufferSize = 24; // ---------------------------------------------------------------------- -// NoLocaleStrtod() -// Exactly like strtod(), except it always behaves as if in the "C" -// locale (i.e. decimal points must be '.'s). +// ToString() are internal help methods used in StrCat() and Join() // ---------------------------------------------------------------------- +namespace internal { +inline string ToString(int i) { + return SimpleItoa(i); +} -LIBPROTOBUF_EXPORT double NoLocaleStrtod(const char* text, char** endptr); +inline string ToString(string a) { + return a; +} +} // namespace internal + +// ---------------------------------------------------------------------- +// StrCat() +// These methods join some strings together. +// ---------------------------------------------------------------------- +template +string StrCat( + const T1& a, const T2& b, const T3& c, const T4& d, const T5& e) { + return internal::ToString(a) + internal::ToString(b) + + internal::ToString(c) + internal::ToString(d) + internal::ToString(e); +} + +template +string StrCat( + const T1& a, const T2& b, const T3& c, const T4& d) { + return internal::ToString(a) + internal::ToString(b) + + internal::ToString(c) + internal::ToString(d); +} + +template +string StrCat(const T1& a, const T2& b, const T3& c) { + return internal::ToString(a) + internal::ToString(b) + + internal::ToString(c); +} + +template +string StrCat(const T1& a, const T2& b) { + return internal::ToString(a) + internal::ToString(b); +} + +// ---------------------------------------------------------------------- +// Join() +// These methods concatenate a range of components into a C++ string, using +// the C-string "delim" as a separator between components. +// ---------------------------------------------------------------------- +template +void Join(Iterator start, Iterator end, + const char* delim, string* result) { + for (Iterator it = start; it != end; ++it) { + if (it != start) { + result->append(delim); + } + result->append(internal::ToString(*it)); + } +} + +template +string Join(const Range& components, + const char* delim) { + string result; + Join(components.begin(), components.end(), delim, &result); + return result; +} + +// ---------------------------------------------------------------------- +// ToHex() +// Return a lower-case hex string representation of the given integer. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT string ToHex(uint64 num); } // namespace protobuf } // namespace google #endif // GOOGLE_PROTOBUF_STUBS_STRUTIL_H__ - - diff --git a/src/google/protobuf/stubs/strutil_unittest.cc b/src/google/protobuf/stubs/strutil_unittest.cc index b9c9253..fde54f0 100644 --- a/src/google/protobuf/stubs/strutil_unittest.cc +++ b/src/google/protobuf/stubs/strutil_unittest.cc @@ -51,27 +51,17 @@ TEST(StringUtilityTest, ImmuneToLocales) { // Set the locale to "C". ASSERT_TRUE(setlocale(LC_NUMERIC, "C") != NULL); - EXPECT_EQ(1.5, NoLocaleStrtod("1.5", NULL)); EXPECT_EQ("1.5", SimpleDtoa(1.5)); EXPECT_EQ("1.5", SimpleFtoa(1.5)); - // Verify that the endptr is set correctly even if not all text was parsed. - const char* text = "1.5f"; - char* endptr; - EXPECT_EQ(1.5, NoLocaleStrtod(text, &endptr)); - EXPECT_EQ(3, endptr - text); - if (setlocale(LC_NUMERIC, "es_ES") == NULL && setlocale(LC_NUMERIC, "es_ES.utf8") == NULL) { // Some systems may not have the desired locale available. GOOGLE_LOG(WARNING) << "Couldn't set locale to es_ES. Skipping this test."; } else { - EXPECT_EQ(1.5, NoLocaleStrtod("1.5", NULL)); EXPECT_EQ("1.5", SimpleDtoa(1.5)); EXPECT_EQ("1.5", SimpleFtoa(1.5)); - EXPECT_EQ(1.5, NoLocaleStrtod(text, &endptr)); - EXPECT_EQ(3, endptr - text); } // Return to original locale. diff --git a/src/google/protobuf/stubs/substitute.cc b/src/google/protobuf/stubs/substitute.cc index b542aaa..259245b 100644 --- a/src/google/protobuf/stubs/substitute.cc +++ b/src/google/protobuf/stubs/substitute.cc @@ -32,7 +32,7 @@ #include #include -#include +#include namespace google { namespace protobuf { diff --git a/src/google/protobuf/stubs/template_util.h b/src/google/protobuf/stubs/template_util.h new file mode 100644 index 0000000..4f30ffa --- /dev/null +++ b/src/google/protobuf/stubs/template_util.h @@ -0,0 +1,138 @@ +// Copyright 2005 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. + +// ---- +// Author: lar@google.com (Laramie Leavitt) +// +// Template metaprogramming utility functions. +// +// This code is compiled directly on many platforms, including client +// platforms like Windows, Mac, and embedded systems. Before making +// any changes here, make sure that you're not breaking any platforms. +// +// +// The names choosen here reflect those used in tr1 and the boost::mpl +// library, there are similar operations used in the Loki library as +// well. I prefer the boost names for 2 reasons: +// 1. I think that portions of the Boost libraries are more likely to +// be included in the c++ standard. +// 2. It is not impossible that some of the boost libraries will be +// included in our own build in the future. +// Both of these outcomes means that we may be able to directly replace +// some of these with boost equivalents. +// +#ifndef GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_ +#define GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_ + +namespace google { +namespace protobuf { +namespace internal { + +// Types small_ and big_ are guaranteed such that sizeof(small_) < +// sizeof(big_) +typedef char small_; + +struct big_ { + char dummy[2]; +}; + +// Identity metafunction. +template +struct identity_ { + typedef T type; +}; + +// integral_constant, defined in tr1, is a wrapper for an integer +// value. We don't really need this generality; we could get away +// with hardcoding the integer type to bool. We use the fully +// general integer_constant for compatibility with tr1. + +template +struct integral_constant { + static const T value = v; + typedef T value_type; + typedef integral_constant type; +}; + +template const T integral_constant::value; + + +// Abbreviations: true_type and false_type are structs that represent boolean +// true and false values. Also define the boost::mpl versions of those names, +// true_ and false_. +typedef integral_constant true_type; +typedef integral_constant false_type; +typedef true_type true_; +typedef false_type false_; + +// if_ is a templatized conditional statement. +// if_ is a compile time evaluation of cond. +// if_<>::type contains A if cond is true, B otherwise. +template +struct if_{ + typedef A type; +}; + +template +struct if_ { + typedef B type; +}; + + +// type_equals_ is a template type comparator, similar to Loki IsSameType. +// type_equals_::value is true iff "A" is the same type as "B". +// +// New code should prefer base::is_same, defined in base/type_traits.h. +// It is functionally identical, but is_same is the standard spelling. +template +struct type_equals_ : public false_ { +}; + +template +struct type_equals_ : public true_ { +}; + +// and_ is a template && operator. +// and_::value evaluates "A::value && B::value". +template +struct and_ : public integral_constant { +}; + +// or_ is a template || operator. +// or_::value evaluates "A::value || B::value". +template +struct or_ : public integral_constant { +}; + + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_ diff --git a/src/google/protobuf/stubs/template_util_unittest.cc b/src/google/protobuf/stubs/template_util_unittest.cc new file mode 100644 index 0000000..b1745e2 --- /dev/null +++ b/src/google/protobuf/stubs/template_util_unittest.cc @@ -0,0 +1,130 @@ +// Copyright 2005 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. + +// ---- +// Author: lar@google.com (Laramie Leavitt) +// +// These tests are really compile time tests. +// If you try to step through this in a debugger +// you will not see any evaluations, merely that +// value is assigned true or false sequentially. + +#include + +#include +#include + +namespace GOOGLE_NAMESPACE = google::protobuf::internal; + +namespace google { +namespace protobuf { +namespace internal { +namespace { + +TEST(TemplateUtilTest, TestSize) { + EXPECT_GT(sizeof(GOOGLE_NAMESPACE::big_), sizeof(GOOGLE_NAMESPACE::small_)); +} + +TEST(TemplateUtilTest, TestIntegralConstants) { + // test the built-in types. + EXPECT_TRUE(true_type::value); + EXPECT_FALSE(false_type::value); + + typedef integral_constant one_type; + EXPECT_EQ(1, one_type::value); +} + +TEST(TemplateUtilTest, TestTemplateIf) { + typedef if_::type if_true; + EXPECT_TRUE(if_true::value); + + typedef if_::type if_false; + EXPECT_FALSE(if_false::value); +} + +TEST(TemplateUtilTest, TestTemplateTypeEquals) { + // Check that the TemplateTypeEquals works correctly. + bool value = false; + + // Test the same type is true. + value = type_equals_::value; + EXPECT_TRUE(value); + + // Test different types are false. + value = type_equals_::value; + EXPECT_FALSE(value); + + // Test type aliasing. + typedef const int foo; + value = type_equals_::value; + EXPECT_TRUE(value); +} + +TEST(TemplateUtilTest, TestTemplateAndOr) { + // Check that the TemplateTypeEquals works correctly. + bool value = false; + + // Yes && Yes == true. + value = and_::value; + EXPECT_TRUE(value); + // Yes && No == false. + value = and_::value; + EXPECT_FALSE(value); + // No && Yes == false. + value = and_::value; + EXPECT_FALSE(value); + // No && No == false. + value = and_::value; + EXPECT_FALSE(value); + + // Yes || Yes == true. + value = or_::value; + EXPECT_TRUE(value); + // Yes || No == true. + value = or_::value; + EXPECT_TRUE(value); + // No || Yes == true. + value = or_::value; + EXPECT_TRUE(value); + // No || No == false. + value = or_::value; + EXPECT_FALSE(value); +} + +TEST(TemplateUtilTest, TestIdentity) { + EXPECT_TRUE( + (type_equals_::type, int>::value)); + EXPECT_TRUE( + (type_equals_::type, void>::value)); +} + +} // anonymous namespace +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/type_traits.h b/src/google/protobuf/stubs/type_traits.h new file mode 100644 index 0000000..e41f5e6 --- /dev/null +++ b/src/google/protobuf/stubs/type_traits.h @@ -0,0 +1,336 @@ +// Copyright (c) 2006, 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. + +// ---- +// Author: Matt Austern +// +// This code is compiled directly on many platforms, including client +// platforms like Windows, Mac, and embedded systems. Before making +// any changes here, make sure that you're not breaking any platforms. +// +// Define a small subset of tr1 type traits. The traits we define are: +// is_integral +// is_floating_point +// is_pointer +// is_enum +// is_reference +// is_pod +// has_trivial_constructor +// has_trivial_copy +// has_trivial_assign +// has_trivial_destructor +// remove_const +// remove_volatile +// remove_cv +// remove_reference +// add_reference +// remove_pointer +// is_same +// is_convertible +// We can add more type traits as required. + +#ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_ +#define GOOGLE_PROTOBUF_TYPE_TRAITS_H_ + +#include // For pair + +#include // For true_type and false_type + +namespace google { +namespace protobuf { +namespace internal { + +template struct is_integral; +template struct is_floating_point; +template struct is_pointer; +// MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least) +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) +// is_enum uses is_convertible, which is not available on MSVC. +template struct is_enum; +#endif +template struct is_reference; +template struct is_pod; +template struct has_trivial_constructor; +template struct has_trivial_copy; +template struct has_trivial_assign; +template struct has_trivial_destructor; +template struct remove_const; +template struct remove_volatile; +template struct remove_cv; +template struct remove_reference; +template struct add_reference; +template struct remove_pointer; +template struct is_same; +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) +template struct is_convertible; +#endif + +// is_integral is false except for the built-in integer types. A +// cv-qualified type is integral if and only if the underlying type is. +template struct is_integral : false_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +#if defined(_MSC_VER) +// wchar_t is not by default a distinct type from unsigned short in +// Microsoft C. +// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx +template<> struct is_integral<__wchar_t> : true_type { }; +#else +template<> struct is_integral : true_type { }; +#endif +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +#ifdef HAVE_LONG_LONG +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +#endif +template struct is_integral : is_integral { }; +template struct is_integral : is_integral { }; +template struct is_integral : is_integral { }; + +// is_floating_point is false except for the built-in floating-point types. +// A cv-qualified type is integral if and only if the underlying type is. +template struct is_floating_point : false_type { }; +template<> struct is_floating_point : true_type { }; +template<> struct is_floating_point : true_type { }; +template<> struct is_floating_point : true_type { }; +template struct is_floating_point + : is_floating_point { }; +template struct is_floating_point + : is_floating_point { }; +template struct is_floating_point + : is_floating_point { }; + +// is_pointer is false except for pointer types. A cv-qualified type (e.g. +// "int* const", as opposed to "int const*") is cv-qualified if and only if +// the underlying type is. +template struct is_pointer : false_type { }; +template struct is_pointer : true_type { }; +template struct is_pointer : is_pointer { }; +template struct is_pointer : is_pointer { }; +template struct is_pointer : is_pointer { }; + +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) + +namespace internal { + +template struct is_class_or_union { + template static small_ tester(void (U::*)()); + template static big_ tester(...); + static const bool value = sizeof(tester(0)) == sizeof(small_); +}; + +// is_convertible chokes if the first argument is an array. That's why +// we use add_reference here. +template struct is_enum_impl + : is_convertible::type, int> { }; + +template struct is_enum_impl : false_type { }; + +} // namespace internal + +// Specified by TR1 [4.5.1] primary type categories. + +// Implementation note: +// +// Each type is either void, integral, floating point, array, pointer, +// reference, member object pointer, member function pointer, enum, +// union or class. Out of these, only integral, floating point, reference, +// class and enum types are potentially convertible to int. Therefore, +// if a type is not a reference, integral, floating point or class and +// is convertible to int, it's a enum. Adding cv-qualification to a type +// does not change whether it's an enum. +// +// Is-convertible-to-int check is done only if all other checks pass, +// because it can't be used with some types (e.g. void or classes with +// inaccessible conversion operators). +template struct is_enum + : internal::is_enum_impl< + is_same::value || + is_integral::value || + is_floating_point::value || + is_reference::value || + internal::is_class_or_union::value, + T> { }; + +template struct is_enum : is_enum { }; +template struct is_enum : is_enum { }; +template struct is_enum : is_enum { }; + +#endif + +// is_reference is false except for reference types. +template struct is_reference : false_type {}; +template struct is_reference : true_type {}; + + +// We can't get is_pod right without compiler help, so fail conservatively. +// We will assume it's false except for arithmetic types, enumerations, +// pointers and cv-qualified versions thereof. Note that std::pair +// is not a POD even if T and U are PODs. +template struct is_pod + : integral_constant::value || + is_floating_point::value || +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) + // is_enum is not available on MSVC. + is_enum::value || +#endif + is_pointer::value)> { }; +template struct is_pod : is_pod { }; +template struct is_pod : is_pod { }; +template struct is_pod : is_pod { }; + + +// We can't get has_trivial_constructor right without compiler help, so +// fail conservatively. We will assume it's false except for: (1) types +// for which is_pod is true. (2) std::pair of types with trivial +// constructors. (3) array of a type with a trivial constructor. +// (4) const versions thereof. +template struct has_trivial_constructor : is_pod { }; +template struct has_trivial_constructor > + : integral_constant::value && + has_trivial_constructor::value)> { }; +template struct has_trivial_constructor + : has_trivial_constructor { }; +template struct has_trivial_constructor + : has_trivial_constructor { }; + +// We can't get has_trivial_copy right without compiler help, so fail +// conservatively. We will assume it's false except for: (1) types +// for which is_pod is true. (2) std::pair of types with trivial copy +// constructors. (3) array of a type with a trivial copy constructor. +// (4) const versions thereof. +template struct has_trivial_copy : is_pod { }; +template struct has_trivial_copy > + : integral_constant::value && + has_trivial_copy::value)> { }; +template struct has_trivial_copy + : has_trivial_copy { }; +template struct has_trivial_copy : has_trivial_copy { }; + +// We can't get has_trivial_assign right without compiler help, so fail +// conservatively. We will assume it's false except for: (1) types +// for which is_pod is true. (2) std::pair of types with trivial copy +// constructors. (3) array of a type with a trivial assign constructor. +template struct has_trivial_assign : is_pod { }; +template struct has_trivial_assign > + : integral_constant::value && + has_trivial_assign::value)> { }; +template struct has_trivial_assign + : has_trivial_assign { }; + +// We can't get has_trivial_destructor right without compiler help, so +// fail conservatively. We will assume it's false except for: (1) types +// for which is_pod is true. (2) std::pair of types with trivial +// destructors. (3) array of a type with a trivial destructor. +// (4) const versions thereof. +template struct has_trivial_destructor : is_pod { }; +template struct has_trivial_destructor > + : integral_constant::value && + has_trivial_destructor::value)> { }; +template struct has_trivial_destructor + : has_trivial_destructor { }; +template struct has_trivial_destructor + : has_trivial_destructor { }; + +// Specified by TR1 [4.7.1] +template struct remove_const { typedef T type; }; +template struct remove_const { typedef T type; }; +template struct remove_volatile { typedef T type; }; +template struct remove_volatile { typedef T type; }; +template struct remove_cv { + typedef typename remove_const::type>::type type; +}; + + +// Specified by TR1 [4.7.2] Reference modifications. +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; + +template struct add_reference { typedef T& type; }; +template struct add_reference { typedef T& type; }; + +// Specified by TR1 [4.7.4] Pointer modifications. +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { + typedef T type; }; + +// Specified by TR1 [4.6] Relationships between types +template struct is_same : public false_type { }; +template struct is_same : public true_type { }; + +// Specified by TR1 [4.6] Relationships between types +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) +namespace internal { + +// This class is an implementation detail for is_convertible, and you +// don't need to know how it works to use is_convertible. For those +// who care: we declare two different functions, one whose argument is +// of type To and one with a variadic argument list. We give them +// return types of different size, so we can use sizeof to trick the +// compiler into telling us which function it would have chosen if we +// had called it with an argument of type From. See Alexandrescu's +// _Modern C++ Design_ for more details on this sort of trick. + +template +struct ConvertHelper { + static small_ Test(To); + static big_ Test(...); + static From Create(); +}; +} // namespace internal + +// Inherits from true_type if From is convertible to To, false_type otherwise. +template +struct is_convertible + : integral_constant::Test( + internal::ConvertHelper::Create())) + == sizeof(small_)> { +}; +#endif + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_TYPE_TRAITS_H_ diff --git a/src/google/protobuf/stubs/type_traits_unittest.cc b/src/google/protobuf/stubs/type_traits_unittest.cc new file mode 100644 index 0000000..7a8cbfb --- /dev/null +++ b/src/google/protobuf/stubs/type_traits_unittest.cc @@ -0,0 +1,628 @@ +// Copyright (c) 2006, 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. + +// ---- +// Author: Matt Austern + +#include + +#include // for exit() +#include +#include +#include + +#include +#include + +typedef int int32; +typedef long int64; + +using std::string; +using std::vector; +using std::pair; + + +// This assertion produces errors like "error: invalid use of +// incomplete type 'struct ::AssertTypesEq'" +// when it fails. +template struct AssertTypesEq; +template struct AssertTypesEq {}; +#define COMPILE_ASSERT_TYPES_EQ(T, U) static_cast(AssertTypesEq()) + +// A user-defined POD type. +struct A { + int n_; +}; + +// A user-defined non-POD type with a trivial copy constructor. +class B { + public: + explicit B(int n) : n_(n) { } + private: + int n_; +}; + +// Another user-defined non-POD type with a trivial copy constructor. +// We will explicitly declare C to have a trivial copy constructor +// by specializing has_trivial_copy. +class C { + public: + explicit C(int n) : n_(n) { } + private: + int n_; +}; + +namespace google { +namespace protobuf { +namespace internal { +template<> struct has_trivial_copy : true_type { }; +} // namespace internal +} // namespace protobuf +} // namespace google + +// Another user-defined non-POD type with a trivial assignment operator. +// We will explicitly declare C to have a trivial assignment operator +// by specializing has_trivial_assign. +class D { + public: + explicit D(int n) : n_(n) { } + private: + int n_; +}; + +namespace google { +namespace protobuf { +namespace internal { +template<> struct has_trivial_assign : true_type { }; +} // namespace internal +} // namespace protobuf +} // namespace google + +// Another user-defined non-POD type with a trivial constructor. +// We will explicitly declare E to have a trivial constructor +// by specializing has_trivial_constructor. +class E { + public: + int n_; +}; + +namespace google { +namespace protobuf { +namespace internal { +template<> struct has_trivial_constructor : true_type { }; +} // namespace internal +} // namespace protobuf +} // namespace google + +// Another user-defined non-POD type with a trivial destructor. +// We will explicitly declare E to have a trivial destructor +// by specializing has_trivial_destructor. +class F { + public: + explicit F(int n) : n_(n) { } + private: + int n_; +}; + +namespace google { +namespace protobuf { +namespace internal { +template<> struct has_trivial_destructor : true_type { }; +} // namespace internal +} // namespace protobuf +} // namespace google + +enum G {}; + +union H {}; + +class I { + public: + operator int() const; +}; + +class J { + private: + operator int() const; +}; + +namespace google { +namespace protobuf { +namespace internal { +namespace { + +// A base class and a derived class that inherits from it, used for +// testing conversion type traits. +class Base { + public: + virtual ~Base() { } +}; + +class Derived : public Base { +}; + +TEST(TypeTraitsTest, TestIsInteger) { + // Verify that is_integral is true for all integer types. + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + + // Verify that is_integral is false for a few non-integer types. + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE((is_integral >::value)); + + // Verify that cv-qualified integral types are still integral, and + // cv-qualified non-integral types are still non-integral. + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE(is_integral::value); +} + +TEST(TypeTraitsTest, TestIsFloating) { + // Verify that is_floating_point is true for all floating-point types. + EXPECT_TRUE(is_floating_point::value); + EXPECT_TRUE(is_floating_point::value); + EXPECT_TRUE(is_floating_point::value); + + // Verify that is_floating_point is false for a few non-float types. + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE((is_floating_point >::value)); + + // Verify that cv-qualified floating point types are still floating, and + // cv-qualified non-floating types are still non-floating. + EXPECT_TRUE(is_floating_point::value); + EXPECT_TRUE(is_floating_point::value); + EXPECT_TRUE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); +} + +TEST(TypeTraitsTest, TestIsPointer) { + // Verify that is_pointer is true for some pointer types. + EXPECT_TRUE(is_pointer::value); + EXPECT_TRUE(is_pointer::value); + EXPECT_TRUE(is_pointer::value); + EXPECT_TRUE(is_pointer::value); + EXPECT_TRUE(is_pointer::value); + + // Verify that is_pointer is false for some non-pointer types. + EXPECT_FALSE(is_pointer::value); + EXPECT_FALSE(is_pointer::value); + EXPECT_FALSE(is_pointer::value); + EXPECT_FALSE(is_pointer >::value); + EXPECT_FALSE(is_pointer::value); + + // A function pointer is a pointer, but a function type, or a function + // reference type, is not. + EXPECT_TRUE(is_pointer::value); + EXPECT_FALSE(is_pointer::value); + EXPECT_FALSE(is_pointer::value); + + // Verify that is_pointer is true for some cv-qualified pointer types, + // and false for some cv-qualified non-pointer types. + EXPECT_TRUE(is_pointer::value); + EXPECT_TRUE(is_pointer::value); + EXPECT_TRUE(is_pointer::value); + EXPECT_FALSE(is_pointer::value); + EXPECT_FALSE(is_pointer >::value); + EXPECT_FALSE(is_pointer::value); +} + +TEST(TypeTraitsTest, TestIsEnum) { +// is_enum isn't supported on MSVC or gcc 3.x +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) + // Verify that is_enum is true for enum types. + EXPECT_TRUE(is_enum::value); + EXPECT_TRUE(is_enum::value); + EXPECT_TRUE(is_enum::value); + EXPECT_TRUE(is_enum::value); + + // Verify that is_enum is false for a few non-enum types. + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); +#endif +} + +TEST(TypeTraitsTest, TestIsReference) { + // Verifies that is_reference is true for all reference types. + typedef float& RefFloat; + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + + + // Verifies that is_reference is false for all non-reference types. + EXPECT_FALSE(is_reference::value); + EXPECT_FALSE(is_reference::value); + EXPECT_FALSE(is_reference::value); + EXPECT_FALSE(is_reference::value); + EXPECT_FALSE(is_reference::value); + EXPECT_FALSE(is_reference::value); + EXPECT_FALSE(is_reference::value); +} + +TEST(TypeTraitsTest, TestAddReference) { + COMPILE_ASSERT_TYPES_EQ(int&, add_reference::type); + COMPILE_ASSERT_TYPES_EQ(const int&, add_reference::type); + COMPILE_ASSERT_TYPES_EQ(volatile int&, + add_reference::type); + COMPILE_ASSERT_TYPES_EQ(const volatile int&, + add_reference::type); + COMPILE_ASSERT_TYPES_EQ(int&, add_reference::type); + COMPILE_ASSERT_TYPES_EQ(const int&, add_reference::type); + COMPILE_ASSERT_TYPES_EQ(volatile int&, + add_reference::type); + COMPILE_ASSERT_TYPES_EQ(const volatile int&, + add_reference::type); +} + +TEST(TypeTraitsTest, TestIsPod) { + // Verify that arithmetic types and pointers are marked as PODs. + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); +#endif + + // Verify that some non-POD types are not marked as PODs. + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE((is_pod >::value)); + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE(is_pod::value); +} + +TEST(TypeTraitsTest, TestHasTrivialConstructor) { + // Verify that arithmetic types and pointers have trivial constructors. + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + + // Verify that pairs and arrays of such types have trivial + // constructors. + typedef int int10[10]; + EXPECT_TRUE((has_trivial_constructor >::value)); + EXPECT_TRUE(has_trivial_constructor::value); + + // Verify that pairs of types without trivial constructors + // are not marked as trivial. + EXPECT_FALSE((has_trivial_constructor >::value)); + EXPECT_FALSE((has_trivial_constructor >::value)); + + // Verify that types without trivial constructors are + // correctly marked as such. + EXPECT_FALSE(has_trivial_constructor::value); + EXPECT_FALSE(has_trivial_constructor >::value); + + // Verify that E, which we have declared to have a trivial + // constructor, is correctly marked as such. + EXPECT_TRUE(has_trivial_constructor::value); +} + +TEST(TypeTraitsTest, TestHasTrivialCopy) { + // Verify that arithmetic types and pointers have trivial copy + // constructors. + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + + // Verify that pairs and arrays of such types have trivial + // copy constructors. + typedef int int10[10]; + EXPECT_TRUE((has_trivial_copy >::value)); + EXPECT_TRUE(has_trivial_copy::value); + + // Verify that pairs of types without trivial copy constructors + // are not marked as trivial. + EXPECT_FALSE((has_trivial_copy >::value)); + EXPECT_FALSE((has_trivial_copy >::value)); + + // Verify that types without trivial copy constructors are + // correctly marked as such. + EXPECT_FALSE(has_trivial_copy::value); + EXPECT_FALSE(has_trivial_copy >::value); + + // Verify that C, which we have declared to have a trivial + // copy constructor, is correctly marked as such. + EXPECT_TRUE(has_trivial_copy::value); +} + +TEST(TypeTraitsTest, TestHasTrivialAssign) { + // Verify that arithmetic types and pointers have trivial assignment + // operators. + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + + // Verify that pairs and arrays of such types have trivial + // assignment operators. + typedef int int10[10]; + EXPECT_TRUE((has_trivial_assign >::value)); + EXPECT_TRUE(has_trivial_assign::value); + + // Verify that pairs of types without trivial assignment operators + // are not marked as trivial. + EXPECT_FALSE((has_trivial_assign >::value)); + EXPECT_FALSE((has_trivial_assign >::value)); + + // Verify that types without trivial assignment operators are + // correctly marked as such. + EXPECT_FALSE(has_trivial_assign::value); + EXPECT_FALSE(has_trivial_assign >::value); + + // Verify that D, which we have declared to have a trivial + // assignment operator, is correctly marked as such. + EXPECT_TRUE(has_trivial_assign::value); +} + +TEST(TypeTraitsTest, TestHasTrivialDestructor) { + // Verify that arithmetic types and pointers have trivial destructors. + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + + // Verify that pairs and arrays of such types have trivial + // destructors. + typedef int int10[10]; + EXPECT_TRUE((has_trivial_destructor >::value)); + EXPECT_TRUE(has_trivial_destructor::value); + + // Verify that pairs of types without trivial destructors + // are not marked as trivial. + EXPECT_FALSE((has_trivial_destructor >::value)); + EXPECT_FALSE((has_trivial_destructor >::value)); + + // Verify that types without trivial destructors are + // correctly marked as such. + EXPECT_FALSE(has_trivial_destructor::value); + EXPECT_FALSE(has_trivial_destructor >::value); + + // Verify that F, which we have declared to have a trivial + // destructor, is correctly marked as such. + EXPECT_TRUE(has_trivial_destructor::value); +} + +// Tests remove_pointer. +TEST(TypeTraitsTest, TestRemovePointer) { + COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); + COMPILE_ASSERT_TYPES_EQ(const int, remove_pointer::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); +} + +TEST(TypeTraitsTest, TestRemoveConst) { + COMPILE_ASSERT_TYPES_EQ(int, remove_const::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_const::type); + COMPILE_ASSERT_TYPES_EQ(int *, remove_const::type); + // TR1 examples. + COMPILE_ASSERT_TYPES_EQ(const int *, remove_const::type); + COMPILE_ASSERT_TYPES_EQ(volatile int, + remove_const::type); +} + +TEST(TypeTraitsTest, TestRemoveVolatile) { + COMPILE_ASSERT_TYPES_EQ(int, remove_volatile::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_volatile::type); + COMPILE_ASSERT_TYPES_EQ(int *, remove_volatile::type); + // TR1 examples. + COMPILE_ASSERT_TYPES_EQ(volatile int *, + remove_volatile::type); + COMPILE_ASSERT_TYPES_EQ(const int, + remove_volatile::type); +} + +TEST(TypeTraitsTest, TestRemoveCV) { + COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); + COMPILE_ASSERT_TYPES_EQ(int *, remove_cv::type); + // TR1 examples. + COMPILE_ASSERT_TYPES_EQ(const volatile int *, + remove_cv::type); + COMPILE_ASSERT_TYPES_EQ(int, + remove_cv::type); +} + +TEST(TypeTraitsTest, TestRemoveReference) { + COMPILE_ASSERT_TYPES_EQ(int, remove_reference::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_reference::type); + COMPILE_ASSERT_TYPES_EQ(const int, remove_reference::type); + COMPILE_ASSERT_TYPES_EQ(int*, remove_reference::type); +} + +TEST(TypeTraitsTest, TestIsSame) { + EXPECT_TRUE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); + + EXPECT_TRUE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); + + EXPECT_TRUE((is_same::value)); + EXPECT_TRUE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); + + EXPECT_TRUE((is_same::value)); + EXPECT_TRUE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); +} + +TEST(TypeTraitsTest, TestConvertible) { +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) + EXPECT_TRUE((is_convertible::value)); + EXPECT_TRUE((is_convertible::value)); + EXPECT_TRUE((is_convertible::value)); + + EXPECT_TRUE((is_convertible::value)); + EXPECT_FALSE((is_convertible::value)); + + EXPECT_TRUE((is_convertible::value)); + EXPECT_FALSE((is_convertible::value)); + EXPECT_TRUE((is_convertible::value)); + EXPECT_FALSE((is_convertible::value)); +#endif +} + +} // anonymous namespace +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc index af8b390..f3cf7a9 100644 --- a/src/google/protobuf/test_util.cc +++ b/src/google/protobuf/test_util.cc @@ -50,6 +50,14 @@ namespace google { namespace protobuf { void TestUtil::SetAllFields(unittest::TestAllTypes* message) { + SetOptionalFields(message); + AddRepeatedFields1(message); + AddRepeatedFields2(message); + SetDefaultFields(message); + SetOneofFields(message); +} + +void TestUtil::SetOptionalFields(unittest::TestAllTypes* message) { message->set_optional_int32 (101); message->set_optional_int64 (102); message->set_optional_uint32 (103); @@ -66,10 +74,12 @@ void TestUtil::SetAllFields(unittest::TestAllTypes* message) { message->set_optional_string ("115"); message->set_optional_bytes ("116"); - message->mutable_optionalgroup ()->set_a(117); - message->mutable_optional_nested_message ()->set_bb(118); - message->mutable_optional_foreign_message()->set_c(119); - message->mutable_optional_import_message ()->set_d(120); + message->mutable_optionalgroup ()->set_a(117); + message->mutable_optional_nested_message ()->set_bb(118); + message->mutable_optional_foreign_message ()->set_c(119); + message->mutable_optional_import_message ()->set_d(120); + message->mutable_optional_public_import_message()->set_e(126); + message->mutable_optional_lazy_message ()->set_bb(127); message->set_optional_nested_enum (unittest::TestAllTypes::BAZ); message->set_optional_foreign_enum(unittest::FOREIGN_BAZ ); @@ -87,9 +97,11 @@ void TestUtil::SetAllFields(unittest::TestAllTypes* message) { message->GetDescriptor()->FindFieldByName("optional_cord"), "125"); #endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} - // ----------------------------------------------------------------- +// ------------------------------------------------------------------- +void TestUtil::AddRepeatedFields1(unittest::TestAllTypes* message) { message->add_repeated_int32 (201); message->add_repeated_int64 (202); message->add_repeated_uint32 (203); @@ -110,6 +122,7 @@ void TestUtil::SetAllFields(unittest::TestAllTypes* message) { message->add_repeated_nested_message ()->set_bb(218); message->add_repeated_foreign_message()->set_c(219); message->add_repeated_import_message ()->set_d(220); + message->add_repeated_lazy_message ()->set_bb(227); message->add_repeated_nested_enum (unittest::TestAllTypes::BAR); message->add_repeated_foreign_enum(unittest::FOREIGN_BAR ); @@ -125,7 +138,9 @@ void TestUtil::SetAllFields(unittest::TestAllTypes* message) { message->GetDescriptor()->FindFieldByName("repeated_cord"), "225"); #endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} +void TestUtil::AddRepeatedFields2(unittest::TestAllTypes* message) { // Add a second one of each field. message->add_repeated_int32 (301); message->add_repeated_int64 (302); @@ -147,6 +162,7 @@ void TestUtil::SetAllFields(unittest::TestAllTypes* message) { message->add_repeated_nested_message ()->set_bb(318); message->add_repeated_foreign_message()->set_c(319); message->add_repeated_import_message ()->set_d(320); + message->add_repeated_lazy_message ()->set_bb(327); message->add_repeated_nested_enum (unittest::TestAllTypes::BAZ); message->add_repeated_foreign_enum(unittest::FOREIGN_BAZ ); @@ -162,9 +178,11 @@ void TestUtil::SetAllFields(unittest::TestAllTypes* message) { message->GetDescriptor()->FindFieldByName("repeated_cord"), "325"); #endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} - // ----------------------------------------------------------------- +// ------------------------------------------------------------------- +void TestUtil::SetDefaultFields(unittest::TestAllTypes* message) { message->set_default_int32 (401); message->set_default_int64 (402); message->set_default_uint32 (403); @@ -220,6 +238,7 @@ void TestUtil::ModifyRepeatedFields(unittest::TestAllTypes* message) { message->mutable_repeated_nested_message (1)->set_bb(518); message->mutable_repeated_foreign_message(1)->set_c(519); message->mutable_repeated_import_message (1)->set_d(520); + message->mutable_repeated_lazy_message (1)->set_bb(527); message->set_repeated_nested_enum (1, unittest::TestAllTypes::FOO); message->set_repeated_foreign_enum(1, unittest::FOREIGN_FOO ); @@ -237,6 +256,14 @@ void TestUtil::ModifyRepeatedFields(unittest::TestAllTypes* message) { #endif // !PROTOBUF_TEST_NO_DESCRIPTORS } +// ------------------------------------------------------------------ +void TestUtil::SetOneofFields(unittest::TestAllTypes* message) { + message->set_oneof_uint32(601); + message->mutable_oneof_nested_message()->set_bb(602); + message->set_oneof_string("603"); + message->set_oneof_bytes("604"); +} + // ------------------------------------------------------------------- void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { @@ -256,15 +283,19 @@ void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { EXPECT_TRUE(message.has_optional_string ()); EXPECT_TRUE(message.has_optional_bytes ()); - EXPECT_TRUE(message.has_optionalgroup ()); - EXPECT_TRUE(message.has_optional_nested_message ()); - EXPECT_TRUE(message.has_optional_foreign_message()); - EXPECT_TRUE(message.has_optional_import_message ()); + EXPECT_TRUE(message.has_optionalgroup ()); + EXPECT_TRUE(message.has_optional_nested_message ()); + EXPECT_TRUE(message.has_optional_foreign_message ()); + EXPECT_TRUE(message.has_optional_import_message ()); + EXPECT_TRUE(message.has_optional_public_import_message()); + EXPECT_TRUE(message.has_optional_lazy_message ()); - EXPECT_TRUE(message.optionalgroup ().has_a()); - EXPECT_TRUE(message.optional_nested_message ().has_bb()); - EXPECT_TRUE(message.optional_foreign_message().has_c()); - EXPECT_TRUE(message.optional_import_message ().has_d()); + EXPECT_TRUE(message.optionalgroup ().has_a()); + EXPECT_TRUE(message.optional_nested_message ().has_bb()); + EXPECT_TRUE(message.optional_foreign_message ().has_c()); + EXPECT_TRUE(message.optional_import_message ().has_d()); + EXPECT_TRUE(message.optional_public_import_message().has_e()); + EXPECT_TRUE(message.optional_lazy_message ().has_bb()); EXPECT_TRUE(message.has_optional_nested_enum ()); EXPECT_TRUE(message.has_optional_foreign_enum()); @@ -287,14 +318,16 @@ void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { EXPECT_EQ(110 , message.optional_sfixed64()); EXPECT_EQ(111 , message.optional_float ()); EXPECT_EQ(112 , message.optional_double ()); - EXPECT_EQ(true , message.optional_bool ()); + EXPECT_TRUE( message.optional_bool ()); EXPECT_EQ("115", message.optional_string ()); EXPECT_EQ("116", message.optional_bytes ()); - EXPECT_EQ(117, message.optionalgroup ().a()); - EXPECT_EQ(118, message.optional_nested_message ().bb()); - EXPECT_EQ(119, message.optional_foreign_message().c()); - EXPECT_EQ(120, message.optional_import_message ().d()); + EXPECT_EQ(117, message.optionalgroup ().a()); + EXPECT_EQ(118, message.optional_nested_message ().bb()); + EXPECT_EQ(119, message.optional_foreign_message ().c()); + EXPECT_EQ(120, message.optional_import_message ().d()); + EXPECT_EQ(126, message.optional_public_import_message ().e()); + EXPECT_EQ(127, message.optional_lazy_message ().bb()); EXPECT_EQ(unittest::TestAllTypes::BAZ, message.optional_nested_enum ()); EXPECT_EQ(unittest::FOREIGN_BAZ , message.optional_foreign_enum()); @@ -323,6 +356,7 @@ void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { ASSERT_EQ(2, message.repeated_nested_message_size ()); ASSERT_EQ(2, message.repeated_foreign_message_size()); ASSERT_EQ(2, message.repeated_import_message_size ()); + ASSERT_EQ(2, message.repeated_lazy_message_size ()); ASSERT_EQ(2, message.repeated_nested_enum_size ()); ASSERT_EQ(2, message.repeated_foreign_enum_size ()); ASSERT_EQ(2, message.repeated_import_enum_size ()); @@ -344,7 +378,7 @@ void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { EXPECT_EQ(210 , message.repeated_sfixed64(0)); EXPECT_EQ(211 , message.repeated_float (0)); EXPECT_EQ(212 , message.repeated_double (0)); - EXPECT_EQ(true , message.repeated_bool (0)); + EXPECT_TRUE( message.repeated_bool (0)); EXPECT_EQ("215", message.repeated_string (0)); EXPECT_EQ("216", message.repeated_bytes (0)); @@ -352,6 +386,7 @@ void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { EXPECT_EQ(218, message.repeated_nested_message (0).bb()); EXPECT_EQ(219, message.repeated_foreign_message(0).c()); EXPECT_EQ(220, message.repeated_import_message (0).d()); + EXPECT_EQ(227, message.repeated_lazy_message (0).bb()); EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0)); @@ -370,7 +405,7 @@ void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { EXPECT_EQ(310 , message.repeated_sfixed64(1)); EXPECT_EQ(311 , message.repeated_float (1)); EXPECT_EQ(312 , message.repeated_double (1)); - EXPECT_EQ(false, message.repeated_bool (1)); + EXPECT_FALSE( message.repeated_bool (1)); EXPECT_EQ("315", message.repeated_string (1)); EXPECT_EQ("316", message.repeated_bytes (1)); @@ -378,6 +413,7 @@ void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { EXPECT_EQ(318, message.repeated_nested_message (1).bb()); EXPECT_EQ(319, message.repeated_foreign_message(1).c()); EXPECT_EQ(320, message.repeated_import_message (1).d()); + EXPECT_EQ(327, message.repeated_lazy_message (1).bb()); EXPECT_EQ(unittest::TestAllTypes::BAZ, message.repeated_nested_enum (1)); EXPECT_EQ(unittest::FOREIGN_BAZ , message.repeated_foreign_enum(1)); @@ -419,7 +455,7 @@ void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { EXPECT_EQ(410 , message.default_sfixed64()); EXPECT_EQ(411 , message.default_float ()); EXPECT_EQ(412 , message.default_double ()); - EXPECT_EQ(false, message.default_bool ()); + EXPECT_FALSE( message.default_bool ()); EXPECT_EQ("415", message.default_string ()); EXPECT_EQ("416", message.default_bytes ()); @@ -427,6 +463,13 @@ void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { EXPECT_EQ(unittest::FOREIGN_FOO , message.default_foreign_enum()); EXPECT_EQ(unittest_import::IMPORT_FOO, message.default_import_enum ()); + + EXPECT_FALSE(message.has_oneof_uint32 ()); + EXPECT_FALSE(message.has_oneof_nested_message()); + EXPECT_FALSE(message.has_oneof_string ()); + EXPECT_TRUE(message.has_oneof_bytes ()); + + EXPECT_EQ("604", message.oneof_bytes()); } // ------------------------------------------------------------------- @@ -449,10 +492,12 @@ void TestUtil::ExpectClear(const unittest::TestAllTypes& message) { EXPECT_FALSE(message.has_optional_string ()); EXPECT_FALSE(message.has_optional_bytes ()); - EXPECT_FALSE(message.has_optionalgroup ()); - EXPECT_FALSE(message.has_optional_nested_message ()); - EXPECT_FALSE(message.has_optional_foreign_message()); - EXPECT_FALSE(message.has_optional_import_message ()); + EXPECT_FALSE(message.has_optionalgroup ()); + EXPECT_FALSE(message.has_optional_nested_message ()); + EXPECT_FALSE(message.has_optional_foreign_message ()); + EXPECT_FALSE(message.has_optional_import_message ()); + EXPECT_FALSE(message.has_optional_public_import_message()); + EXPECT_FALSE(message.has_optional_lazy_message ()); EXPECT_FALSE(message.has_optional_nested_enum ()); EXPECT_FALSE(message.has_optional_foreign_enum()); @@ -474,20 +519,24 @@ void TestUtil::ExpectClear(const unittest::TestAllTypes& message) { EXPECT_EQ(0 , message.optional_sfixed64()); EXPECT_EQ(0 , message.optional_float ()); EXPECT_EQ(0 , message.optional_double ()); - EXPECT_EQ(false, message.optional_bool ()); + EXPECT_FALSE( message.optional_bool ()); EXPECT_EQ("" , message.optional_string ()); EXPECT_EQ("" , message.optional_bytes ()); // Embedded messages should also be clear. - EXPECT_FALSE(message.optionalgroup ().has_a()); - EXPECT_FALSE(message.optional_nested_message ().has_bb()); - EXPECT_FALSE(message.optional_foreign_message().has_c()); - EXPECT_FALSE(message.optional_import_message ().has_d()); - - EXPECT_EQ(0, message.optionalgroup ().a()); - EXPECT_EQ(0, message.optional_nested_message ().bb()); - EXPECT_EQ(0, message.optional_foreign_message().c()); - EXPECT_EQ(0, message.optional_import_message ().d()); + EXPECT_FALSE(message.optionalgroup ().has_a()); + EXPECT_FALSE(message.optional_nested_message ().has_bb()); + EXPECT_FALSE(message.optional_foreign_message ().has_c()); + EXPECT_FALSE(message.optional_import_message ().has_d()); + EXPECT_FALSE(message.optional_public_import_message().has_e()); + EXPECT_FALSE(message.optional_lazy_message ().has_bb()); + + EXPECT_EQ(0, message.optionalgroup ().a()); + EXPECT_EQ(0, message.optional_nested_message ().bb()); + EXPECT_EQ(0, message.optional_foreign_message ().c()); + EXPECT_EQ(0, message.optional_import_message ().d()); + EXPECT_EQ(0, message.optional_public_import_message().e()); + EXPECT_EQ(0, message.optional_lazy_message ().bb()); // Enums without defaults are set to the first value in the enum. EXPECT_EQ(unittest::TestAllTypes::FOO, message.optional_nested_enum ()); @@ -516,6 +565,7 @@ void TestUtil::ExpectClear(const unittest::TestAllTypes& message) { EXPECT_EQ(0, message.repeated_nested_message_size ()); EXPECT_EQ(0, message.repeated_foreign_message_size()); EXPECT_EQ(0, message.repeated_import_message_size ()); + EXPECT_EQ(0, message.repeated_lazy_message_size ()); EXPECT_EQ(0, message.repeated_nested_enum_size ()); EXPECT_EQ(0, message.repeated_foreign_enum_size ()); EXPECT_EQ(0, message.repeated_import_enum_size ()); @@ -558,7 +608,7 @@ void TestUtil::ExpectClear(const unittest::TestAllTypes& message) { EXPECT_EQ(-50 , message.default_sfixed64()); EXPECT_EQ( 51.5 , message.default_float ()); EXPECT_EQ( 52e3 , message.default_double ()); - EXPECT_EQ(true , message.default_bool ()); + EXPECT_TRUE( message.default_bool ()); EXPECT_EQ("hello", message.default_string ()); EXPECT_EQ("world", message.default_bytes ()); @@ -566,6 +616,11 @@ void TestUtil::ExpectClear(const unittest::TestAllTypes& message) { EXPECT_EQ(unittest::FOREIGN_BAR , message.default_foreign_enum()); EXPECT_EQ(unittest_import::IMPORT_BAR, message.default_import_enum ()); + + EXPECT_FALSE(message.has_oneof_uint32 ()); + EXPECT_FALSE(message.has_oneof_nested_message()); + EXPECT_FALSE(message.has_oneof_string ()); + EXPECT_FALSE(message.has_oneof_bytes ()); } // ------------------------------------------------------------------- @@ -595,6 +650,7 @@ void TestUtil::ExpectRepeatedFieldsModified( ASSERT_EQ(2, message.repeated_nested_message_size ()); ASSERT_EQ(2, message.repeated_foreign_message_size()); ASSERT_EQ(2, message.repeated_import_message_size ()); + ASSERT_EQ(2, message.repeated_lazy_message_size ()); ASSERT_EQ(2, message.repeated_nested_enum_size ()); ASSERT_EQ(2, message.repeated_foreign_enum_size ()); ASSERT_EQ(2, message.repeated_import_enum_size ()); @@ -616,7 +672,7 @@ void TestUtil::ExpectRepeatedFieldsModified( EXPECT_EQ(210 , message.repeated_sfixed64(0)); EXPECT_EQ(211 , message.repeated_float (0)); EXPECT_EQ(212 , message.repeated_double (0)); - EXPECT_EQ(true , message.repeated_bool (0)); + EXPECT_TRUE( message.repeated_bool (0)); EXPECT_EQ("215", message.repeated_string (0)); EXPECT_EQ("216", message.repeated_bytes (0)); @@ -624,6 +680,7 @@ void TestUtil::ExpectRepeatedFieldsModified( EXPECT_EQ(218, message.repeated_nested_message (0).bb()); EXPECT_EQ(219, message.repeated_foreign_message(0).c()); EXPECT_EQ(220, message.repeated_import_message (0).d()); + EXPECT_EQ(227, message.repeated_lazy_message (0).bb()); EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0)); EXPECT_EQ(unittest::FOREIGN_BAR , message.repeated_foreign_enum(0)); @@ -643,7 +700,7 @@ void TestUtil::ExpectRepeatedFieldsModified( EXPECT_EQ(510 , message.repeated_sfixed64(1)); EXPECT_EQ(511 , message.repeated_float (1)); EXPECT_EQ(512 , message.repeated_double (1)); - EXPECT_EQ(true , message.repeated_bool (1)); + EXPECT_TRUE( message.repeated_bool (1)); EXPECT_EQ("515", message.repeated_string (1)); EXPECT_EQ("516", message.repeated_bytes (1)); @@ -651,6 +708,7 @@ void TestUtil::ExpectRepeatedFieldsModified( EXPECT_EQ(518, message.repeated_nested_message (1).bb()); EXPECT_EQ(519, message.repeated_foreign_message(1).c()); EXPECT_EQ(520, message.repeated_import_message (1).d()); + EXPECT_EQ(527, message.repeated_lazy_message (1).bb()); EXPECT_EQ(unittest::TestAllTypes::FOO, message.repeated_nested_enum (1)); EXPECT_EQ(unittest::FOREIGN_FOO , message.repeated_foreign_enum(1)); @@ -775,7 +833,7 @@ void TestUtil::ExpectPackedFieldsSet(const unittest::TestPackedTypes& message) { EXPECT_EQ(610 , message.packed_sfixed64(0)); EXPECT_EQ(611 , message.packed_float (0)); EXPECT_EQ(612 , message.packed_double (0)); - EXPECT_EQ(true , message.packed_bool (0)); + EXPECT_TRUE( message.packed_bool (0)); EXPECT_EQ(unittest::FOREIGN_BAR, message.packed_enum(0)); EXPECT_EQ(701 , message.packed_int32 (1)); @@ -790,7 +848,7 @@ void TestUtil::ExpectPackedFieldsSet(const unittest::TestPackedTypes& message) { EXPECT_EQ(710 , message.packed_sfixed64(1)); EXPECT_EQ(711 , message.packed_float (1)); EXPECT_EQ(712 , message.packed_double (1)); - EXPECT_EQ(false, message.packed_bool (1)); + EXPECT_FALSE( message.packed_bool (1)); EXPECT_EQ(unittest::FOREIGN_BAZ, message.packed_enum(1)); } @@ -825,7 +883,7 @@ void TestUtil::ExpectUnpackedFieldsSet( EXPECT_EQ(610 , message.unpacked_sfixed64(0)); EXPECT_EQ(611 , message.unpacked_float (0)); EXPECT_EQ(612 , message.unpacked_double (0)); - EXPECT_EQ(true , message.unpacked_bool (0)); + EXPECT_TRUE( message.unpacked_bool (0)); EXPECT_EQ(unittest::FOREIGN_BAR, message.unpacked_enum(0)); EXPECT_EQ(701 , message.unpacked_int32 (1)); @@ -840,7 +898,7 @@ void TestUtil::ExpectUnpackedFieldsSet( EXPECT_EQ(710 , message.unpacked_sfixed64(1)); EXPECT_EQ(711 , message.unpacked_float (1)); EXPECT_EQ(712 , message.unpacked_double (1)); - EXPECT_EQ(false, message.unpacked_bool (1)); + EXPECT_FALSE( message.unpacked_bool (1)); EXPECT_EQ(unittest::FOREIGN_BAZ, message.unpacked_enum(1)); } @@ -897,7 +955,7 @@ void TestUtil::ExpectPackedFieldsModified( EXPECT_EQ(610 , message.packed_sfixed64(0)); EXPECT_EQ(611 , message.packed_float (0)); EXPECT_EQ(612 , message.packed_double (0)); - EXPECT_EQ(true , message.packed_bool (0)); + EXPECT_TRUE( message.packed_bool (0)); EXPECT_EQ(unittest::FOREIGN_BAR, message.packed_enum(0)); // Actually verify the second (modified) elements now. EXPECT_EQ(801 , message.packed_int32 (1)); @@ -912,7 +970,7 @@ void TestUtil::ExpectPackedFieldsModified( EXPECT_EQ(810 , message.packed_sfixed64(1)); EXPECT_EQ(811 , message.packed_float (1)); EXPECT_EQ(812 , message.packed_double (1)); - EXPECT_EQ(true , message.packed_bool (1)); + EXPECT_TRUE( message.packed_bool (1)); EXPECT_EQ(unittest::FOREIGN_FOO, message.packed_enum(1)); } @@ -953,6 +1011,9 @@ void TestUtil::SetAllExtensions(unittest::TestAllExtensions* message) { message->SetExtension(unittest::optional_string_piece_extension, "124"); message->SetExtension(unittest::optional_cord_extension, "125"); + message->MutableExtension(unittest::optional_public_import_message_extension)->set_e(126); + message->MutableExtension(unittest::optional_lazy_message_extension)->set_bb(127); + // ----------------------------------------------------------------- message->AddExtension(unittest::repeated_int32_extension , 201); @@ -975,6 +1036,7 @@ void TestUtil::SetAllExtensions(unittest::TestAllExtensions* message) { message->AddExtension(unittest::repeated_nested_message_extension )->set_bb(218); message->AddExtension(unittest::repeated_foreign_message_extension)->set_c(219); message->AddExtension(unittest::repeated_import_message_extension )->set_d(220); + message->AddExtension(unittest::repeated_lazy_message_extension )->set_bb(227); message->AddExtension(unittest::repeated_nested_enum_extension , unittest::TestAllTypes::BAR); message->AddExtension(unittest::repeated_foreign_enum_extension, unittest::FOREIGN_BAR ); @@ -1004,6 +1066,7 @@ void TestUtil::SetAllExtensions(unittest::TestAllExtensions* message) { message->AddExtension(unittest::repeated_nested_message_extension )->set_bb(318); message->AddExtension(unittest::repeated_foreign_message_extension)->set_c(319); message->AddExtension(unittest::repeated_import_message_extension )->set_d(320); + message->AddExtension(unittest::repeated_lazy_message_extension )->set_bb(327); message->AddExtension(unittest::repeated_nested_enum_extension , unittest::TestAllTypes::BAZ); message->AddExtension(unittest::repeated_foreign_enum_extension, unittest::FOREIGN_BAZ ); @@ -1036,6 +1099,15 @@ void TestUtil::SetAllExtensions(unittest::TestAllExtensions* message) { message->SetExtension(unittest::default_string_piece_extension, "424"); message->SetExtension(unittest::default_cord_extension, "425"); + + SetOneofFields(message); +} + +void TestUtil::SetOneofFields(unittest::TestAllExtensions* message) { + message->SetExtension(unittest::oneof_uint32_extension, 601); + message->MutableExtension(unittest::oneof_nested_message_extension)->set_bb(602); + message->SetExtension(unittest::oneof_string_extension, "603"); + message->SetExtension(unittest::oneof_bytes_extension, "604"); } // ------------------------------------------------------------------- @@ -1073,6 +1145,7 @@ void TestUtil::ModifyRepeatedExtensions(unittest::TestAllExtensions* message) { message->MutableExtension(unittest::repeated_nested_message_extension , 1)->set_bb(518); message->MutableExtension(unittest::repeated_foreign_message_extension, 1)->set_c(519); message->MutableExtension(unittest::repeated_import_message_extension , 1)->set_d(520); + message->MutableExtension(unittest::repeated_lazy_message_extension , 1)->set_bb(527); message->SetExtension(unittest::repeated_nested_enum_extension , 1, unittest::TestAllTypes::FOO); message->SetExtension(unittest::repeated_foreign_enum_extension, 1, unittest::FOREIGN_FOO ); @@ -1102,15 +1175,19 @@ void TestUtil::ExpectAllExtensionsSet( EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension )); EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension)); - EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension )); + EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension )); + EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension )); + EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension )); + EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension )); + EXPECT_TRUE(message.HasExtension(unittest::optional_public_import_message_extension)); + EXPECT_TRUE(message.HasExtension(unittest::optional_lazy_message_extension )); - EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension ).has_a()); - EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension ).has_bb()); - EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension).has_c()); - EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension ).has_d()); + EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension ).has_a()); + EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension ).has_bb()); + EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension ).has_c()); + EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension ).has_d()); + EXPECT_TRUE(message.GetExtension(unittest::optional_public_import_message_extension).has_e()); + EXPECT_TRUE(message.GetExtension(unittest::optional_lazy_message_extension ).has_bb()); EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension )); EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension)); @@ -1131,7 +1208,7 @@ void TestUtil::ExpectAllExtensionsSet( EXPECT_EQ(110 , message.GetExtension(unittest::optional_sfixed64_extension)); EXPECT_EQ(111 , message.GetExtension(unittest::optional_float_extension )); EXPECT_EQ(112 , message.GetExtension(unittest::optional_double_extension )); - EXPECT_EQ(true , message.GetExtension(unittest::optional_bool_extension )); + EXPECT_TRUE( message.GetExtension(unittest::optional_bool_extension )); EXPECT_EQ("115", message.GetExtension(unittest::optional_string_extension )); EXPECT_EQ("116", message.GetExtension(unittest::optional_bytes_extension )); @@ -1146,6 +1223,8 @@ void TestUtil::ExpectAllExtensionsSet( EXPECT_EQ("124", message.GetExtension(unittest::optional_string_piece_extension)); EXPECT_EQ("125", message.GetExtension(unittest::optional_cord_extension)); + EXPECT_EQ(126, message.GetExtension(unittest::optional_public_import_message_extension ).e()); + EXPECT_EQ(127, message.GetExtension(unittest::optional_lazy_message_extension).bb()); // ----------------------------------------------------------------- @@ -1169,6 +1248,7 @@ void TestUtil::ExpectAllExtensionsSet( ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension)); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension )); @@ -1188,7 +1268,7 @@ void TestUtil::ExpectAllExtensionsSet( EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension, 0)); EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension , 0)); EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension , 0)); - EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension , 0)); + EXPECT_TRUE( message.GetExtension(unittest::repeated_bool_extension , 0)); EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension , 0)); EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension , 0)); @@ -1196,6 +1276,7 @@ void TestUtil::ExpectAllExtensionsSet( EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb()); EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c()); EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d()); + EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb()); EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0)); EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 0)); @@ -1216,7 +1297,7 @@ void TestUtil::ExpectAllExtensionsSet( EXPECT_EQ(310 , message.GetExtension(unittest::repeated_sfixed64_extension, 1)); EXPECT_EQ(311 , message.GetExtension(unittest::repeated_float_extension , 1)); EXPECT_EQ(312 , message.GetExtension(unittest::repeated_double_extension , 1)); - EXPECT_EQ(false, message.GetExtension(unittest::repeated_bool_extension , 1)); + EXPECT_FALSE( message.GetExtension(unittest::repeated_bool_extension , 1)); EXPECT_EQ("315", message.GetExtension(unittest::repeated_string_extension , 1)); EXPECT_EQ("316", message.GetExtension(unittest::repeated_bytes_extension , 1)); @@ -1224,6 +1305,7 @@ void TestUtil::ExpectAllExtensionsSet( EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb()); EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c()); EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension , 1).d()); + EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension , 1).bb()); EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::repeated_nested_enum_extension , 1)); EXPECT_EQ(unittest::FOREIGN_BAZ , message.GetExtension(unittest::repeated_foreign_enum_extension, 1)); @@ -1269,7 +1351,7 @@ void TestUtil::ExpectAllExtensionsSet( EXPECT_EQ(410 , message.GetExtension(unittest::default_sfixed64_extension)); EXPECT_EQ(411 , message.GetExtension(unittest::default_float_extension )); EXPECT_EQ(412 , message.GetExtension(unittest::default_double_extension )); - EXPECT_EQ(false, message.GetExtension(unittest::default_bool_extension )); + EXPECT_FALSE( message.GetExtension(unittest::default_bool_extension )); EXPECT_EQ("415", message.GetExtension(unittest::default_string_extension )); EXPECT_EQ("416", message.GetExtension(unittest::default_bytes_extension )); @@ -1279,6 +1361,16 @@ void TestUtil::ExpectAllExtensionsSet( EXPECT_EQ("424", message.GetExtension(unittest::default_string_piece_extension)); EXPECT_EQ("425", message.GetExtension(unittest::default_cord_extension)); + + EXPECT_TRUE(message.HasExtension(unittest::oneof_uint32_extension)); + EXPECT_TRUE(message.GetExtension(unittest::oneof_nested_message_extension).has_bb()); + EXPECT_TRUE(message.HasExtension(unittest::oneof_string_extension)); + EXPECT_TRUE(message.HasExtension(unittest::oneof_bytes_extension)); + + EXPECT_EQ(601, message.GetExtension(unittest::oneof_uint32_extension)); + EXPECT_EQ(602, message.GetExtension(unittest::oneof_nested_message_extension).bb()); + EXPECT_EQ("603", message.GetExtension(unittest::oneof_string_extension)); + EXPECT_EQ("604", message.GetExtension(unittest::oneof_bytes_extension)); } // ------------------------------------------------------------------- @@ -1307,10 +1399,12 @@ void TestUtil::ExpectExtensionsClear( EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension )); EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension)); - EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension )); + EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension )); + EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension )); + EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension )); + EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension )); + EXPECT_FALSE(message.HasExtension(unittest::optional_public_import_message_extension)); + EXPECT_FALSE(message.HasExtension(unittest::optional_lazy_message_extension )); EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension )); EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension)); @@ -1332,20 +1426,24 @@ void TestUtil::ExpectExtensionsClear( EXPECT_EQ(0 , message.GetExtension(unittest::optional_sfixed64_extension)); EXPECT_EQ(0 , message.GetExtension(unittest::optional_float_extension )); EXPECT_EQ(0 , message.GetExtension(unittest::optional_double_extension )); - EXPECT_EQ(false, message.GetExtension(unittest::optional_bool_extension )); + EXPECT_FALSE( message.GetExtension(unittest::optional_bool_extension )); EXPECT_EQ("" , message.GetExtension(unittest::optional_string_extension )); EXPECT_EQ("" , message.GetExtension(unittest::optional_bytes_extension )); // Embedded messages should also be clear. - EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension ).has_a()); - EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension ).has_bb()); - EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension).has_c()); - EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension ).has_d()); - - EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension ).a()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension ).bb()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension).c()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension ).d()); + EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension ).has_a()); + EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension ).has_bb()); + EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension ).has_c()); + EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension ).has_d()); + EXPECT_FALSE(message.GetExtension(unittest::optional_public_import_message_extension).has_e()); + EXPECT_FALSE(message.GetExtension(unittest::optional_lazy_message_extension ).has_bb()); + + EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension ).a()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension ).bb()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension ).c()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension ).d()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_public_import_message_extension).e()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_lazy_message_extension ).bb()); // Enums without defaults are set to the first value in the enum. EXPECT_EQ(unittest::TestAllTypes::FOO, message.GetExtension(unittest::optional_nested_enum_extension )); @@ -1376,6 +1474,7 @@ void TestUtil::ExpectExtensionsClear( EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension )); EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension)); EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_lazy_message_extension )); EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension )); EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension )); EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension )); @@ -1420,7 +1519,7 @@ void TestUtil::ExpectExtensionsClear( EXPECT_EQ(-50 , message.GetExtension(unittest::default_sfixed64_extension)); EXPECT_EQ( 51.5 , message.GetExtension(unittest::default_float_extension )); EXPECT_EQ( 52e3 , message.GetExtension(unittest::default_double_extension )); - EXPECT_EQ(true , message.GetExtension(unittest::default_bool_extension )); + EXPECT_TRUE( message.GetExtension(unittest::default_bool_extension )); EXPECT_EQ("hello", message.GetExtension(unittest::default_string_extension )); EXPECT_EQ("world", message.GetExtension(unittest::default_bytes_extension )); @@ -1430,6 +1529,11 @@ void TestUtil::ExpectExtensionsClear( EXPECT_EQ("abc", message.GetExtension(unittest::default_string_piece_extension)); EXPECT_EQ("123", message.GetExtension(unittest::default_cord_extension)); + + EXPECT_FALSE(message.HasExtension(unittest::oneof_uint32_extension)); + EXPECT_FALSE(message.GetExtension(unittest::oneof_nested_message_extension).has_bb()); + EXPECT_FALSE(message.HasExtension(unittest::oneof_string_extension)); + EXPECT_FALSE(message.HasExtension(unittest::oneof_bytes_extension)); } // ------------------------------------------------------------------- @@ -1459,6 +1563,7 @@ void TestUtil::ExpectRepeatedExtensionsModified( ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension)); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension )); @@ -1478,7 +1583,7 @@ void TestUtil::ExpectRepeatedExtensionsModified( EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension, 0)); EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension , 0)); EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension , 0)); - EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension , 0)); + EXPECT_TRUE( message.GetExtension(unittest::repeated_bool_extension , 0)); EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension , 0)); EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension , 0)); @@ -1486,6 +1591,7 @@ void TestUtil::ExpectRepeatedExtensionsModified( EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb()); EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c()); EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d()); + EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb()); EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0)); EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 0)); @@ -1507,7 +1613,7 @@ void TestUtil::ExpectRepeatedExtensionsModified( EXPECT_EQ(510 , message.GetExtension(unittest::repeated_sfixed64_extension, 1)); EXPECT_EQ(511 , message.GetExtension(unittest::repeated_float_extension , 1)); EXPECT_EQ(512 , message.GetExtension(unittest::repeated_double_extension , 1)); - EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension , 1)); + EXPECT_TRUE( message.GetExtension(unittest::repeated_bool_extension , 1)); EXPECT_EQ("515", message.GetExtension(unittest::repeated_string_extension , 1)); EXPECT_EQ("516", message.GetExtension(unittest::repeated_bytes_extension , 1)); @@ -1515,6 +1621,7 @@ void TestUtil::ExpectRepeatedExtensionsModified( EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb()); EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c()); EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension , 1).d()); + EXPECT_EQ(527, message.GetExtension(unittest::repeated_lazy_message_extension , 1).bb()); EXPECT_EQ(unittest::TestAllTypes::FOO, message.GetExtension(unittest::repeated_nested_enum_extension , 1)); EXPECT_EQ(unittest::FOREIGN_FOO , message.GetExtension(unittest::repeated_foreign_enum_extension, 1)); @@ -1609,7 +1716,7 @@ void TestUtil::ExpectPackedExtensionsSet( EXPECT_EQ(610 , message.GetExtension(unittest::packed_sfixed64_extension, 0)); EXPECT_EQ(611 , message.GetExtension(unittest::packed_float_extension , 0)); EXPECT_EQ(612 , message.GetExtension(unittest::packed_double_extension , 0)); - EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension , 0)); + EXPECT_TRUE( message.GetExtension(unittest::packed_bool_extension , 0)); EXPECT_EQ(unittest::FOREIGN_BAR, message.GetExtension(unittest::packed_enum_extension, 0)); EXPECT_EQ(701 , message.GetExtension(unittest::packed_int32_extension , 1)); @@ -1624,7 +1731,7 @@ void TestUtil::ExpectPackedExtensionsSet( EXPECT_EQ(710 , message.GetExtension(unittest::packed_sfixed64_extension, 1)); EXPECT_EQ(711 , message.GetExtension(unittest::packed_float_extension , 1)); EXPECT_EQ(712 , message.GetExtension(unittest::packed_double_extension , 1)); - EXPECT_EQ(false, message.GetExtension(unittest::packed_bool_extension , 1)); + EXPECT_FALSE( message.GetExtension(unittest::packed_bool_extension , 1)); EXPECT_EQ(unittest::FOREIGN_BAZ, message.GetExtension(unittest::packed_enum_extension, 1)); } @@ -1679,7 +1786,7 @@ void TestUtil::ExpectPackedExtensionsModified( EXPECT_EQ(610 , message.GetExtension(unittest::packed_sfixed64_extension, 0)); EXPECT_EQ(611 , message.GetExtension(unittest::packed_float_extension , 0)); EXPECT_EQ(612 , message.GetExtension(unittest::packed_double_extension , 0)); - EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension , 0)); + EXPECT_TRUE( message.GetExtension(unittest::packed_bool_extension , 0)); EXPECT_EQ(unittest::FOREIGN_BAR, message.GetExtension(unittest::packed_enum_extension, 0)); @@ -1696,13 +1803,64 @@ void TestUtil::ExpectPackedExtensionsModified( EXPECT_EQ(810 , message.GetExtension(unittest::packed_sfixed64_extension, 1)); EXPECT_EQ(811 , message.GetExtension(unittest::packed_float_extension , 1)); EXPECT_EQ(812 , message.GetExtension(unittest::packed_double_extension , 1)); - EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension , 1)); + EXPECT_TRUE( message.GetExtension(unittest::packed_bool_extension , 1)); EXPECT_EQ(unittest::FOREIGN_FOO, message.GetExtension(unittest::packed_enum_extension, 1)); } // ------------------------------------------------------------------- +void TestUtil::ExpectUnpackedExtensionsSet( + const unittest::TestUnpackedExtensions& message) { + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_int32_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_int64_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_uint32_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_uint64_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sint32_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sint64_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_fixed32_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_fixed64_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_float_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_double_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_bool_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_enum_extension )); + + EXPECT_EQ(601 , message.GetExtension(unittest::unpacked_int32_extension , 0)); + EXPECT_EQ(602 , message.GetExtension(unittest::unpacked_int64_extension , 0)); + EXPECT_EQ(603 , message.GetExtension(unittest::unpacked_uint32_extension , 0)); + EXPECT_EQ(604 , message.GetExtension(unittest::unpacked_uint64_extension , 0)); + EXPECT_EQ(605 , message.GetExtension(unittest::unpacked_sint32_extension , 0)); + EXPECT_EQ(606 , message.GetExtension(unittest::unpacked_sint64_extension , 0)); + EXPECT_EQ(607 , message.GetExtension(unittest::unpacked_fixed32_extension , 0)); + EXPECT_EQ(608 , message.GetExtension(unittest::unpacked_fixed64_extension , 0)); + EXPECT_EQ(609 , message.GetExtension(unittest::unpacked_sfixed32_extension, 0)); + EXPECT_EQ(610 , message.GetExtension(unittest::unpacked_sfixed64_extension, 0)); + EXPECT_EQ(611 , message.GetExtension(unittest::unpacked_float_extension , 0)); + EXPECT_EQ(612 , message.GetExtension(unittest::unpacked_double_extension , 0)); + EXPECT_EQ(true , message.GetExtension(unittest::unpacked_bool_extension , 0)); + EXPECT_EQ(unittest::FOREIGN_BAR, + message.GetExtension(unittest::unpacked_enum_extension, 0)); + EXPECT_EQ(701 , message.GetExtension(unittest::unpacked_int32_extension , 1)); + EXPECT_EQ(702 , message.GetExtension(unittest::unpacked_int64_extension , 1)); + EXPECT_EQ(703 , message.GetExtension(unittest::unpacked_uint32_extension , 1)); + EXPECT_EQ(704 , message.GetExtension(unittest::unpacked_uint64_extension , 1)); + EXPECT_EQ(705 , message.GetExtension(unittest::unpacked_sint32_extension , 1)); + EXPECT_EQ(706 , message.GetExtension(unittest::unpacked_sint64_extension , 1)); + EXPECT_EQ(707 , message.GetExtension(unittest::unpacked_fixed32_extension , 1)); + EXPECT_EQ(708 , message.GetExtension(unittest::unpacked_fixed64_extension , 1)); + EXPECT_EQ(709 , message.GetExtension(unittest::unpacked_sfixed32_extension, 1)); + EXPECT_EQ(710 , message.GetExtension(unittest::unpacked_sfixed64_extension, 1)); + EXPECT_EQ(711 , message.GetExtension(unittest::unpacked_float_extension , 1)); + EXPECT_EQ(712 , message.GetExtension(unittest::unpacked_double_extension , 1)); + EXPECT_EQ(false, message.GetExtension(unittest::unpacked_bool_extension , 1)); + EXPECT_EQ(unittest::FOREIGN_BAZ, + message.GetExtension(unittest::unpacked_enum_extension, 1)); +} + +// ------------------------------------------------------------------- + void TestUtil::ExpectAllFieldsAndExtensionsInOrder(const string& serialized) { // We set each field individually, serialize separately, and concatenate all // the strings in canonical order to determine the expected serialization. @@ -1750,6 +1908,7 @@ void TestUtil::ExpectLastRepeatedsRemoved( ASSERT_EQ(1, message.repeated_nested_message_size ()); ASSERT_EQ(1, message.repeated_foreign_message_size()); ASSERT_EQ(1, message.repeated_import_message_size ()); + ASSERT_EQ(1, message.repeated_import_message_size ()); ASSERT_EQ(1, message.repeated_nested_enum_size ()); ASSERT_EQ(1, message.repeated_foreign_enum_size ()); ASSERT_EQ(1, message.repeated_import_enum_size ()); @@ -1772,7 +1931,7 @@ void TestUtil::ExpectLastRepeatedsRemoved( EXPECT_EQ(210 , message.repeated_sfixed64(0)); EXPECT_EQ(211 , message.repeated_float (0)); EXPECT_EQ(212 , message.repeated_double (0)); - EXPECT_EQ(true , message.repeated_bool (0)); + EXPECT_TRUE( message.repeated_bool (0)); EXPECT_EQ("215", message.repeated_string (0)); EXPECT_EQ("216", message.repeated_bytes (0)); @@ -1780,6 +1939,7 @@ void TestUtil::ExpectLastRepeatedsRemoved( EXPECT_EQ(218, message.repeated_nested_message (0).bb()); EXPECT_EQ(219, message.repeated_foreign_message(0).c()); EXPECT_EQ(220, message.repeated_import_message (0).d()); + EXPECT_EQ(220, message.repeated_import_message (0).d()); EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0)); EXPECT_EQ(unittest::FOREIGN_BAR , message.repeated_foreign_enum(0)); @@ -1810,6 +1970,7 @@ void TestUtil::ExpectLastRepeatedExtensionsRemoved( ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_message_extension )); ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_message_extension)); ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_message_extension )); + ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_lazy_message_extension )); ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_enum_extension )); ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_enum_extension )); ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_enum_extension )); @@ -1830,7 +1991,7 @@ void TestUtil::ExpectLastRepeatedExtensionsRemoved( EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension, 0)); EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension , 0)); EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension , 0)); - EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension , 0)); + EXPECT_TRUE( message.GetExtension(unittest::repeated_bool_extension , 0)); EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension , 0)); EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension , 0)); @@ -1838,6 +1999,7 @@ void TestUtil::ExpectLastRepeatedExtensionsRemoved( EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb()); EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c()); EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d()); + EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb()); EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0)); EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 0)); @@ -1847,6 +2009,36 @@ void TestUtil::ExpectLastRepeatedExtensionsRemoved( EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 0)); } +void TestUtil::ExpectLastRepeatedsReleased( + const unittest::TestAllTypes& message) { + ASSERT_EQ(1, message.repeatedgroup_size ()); + ASSERT_EQ(1, message.repeated_nested_message_size ()); + ASSERT_EQ(1, message.repeated_foreign_message_size()); + ASSERT_EQ(1, message.repeated_import_message_size ()); + ASSERT_EQ(1, message.repeated_import_message_size ()); + + EXPECT_EQ(217, message.repeatedgroup (0).a()); + EXPECT_EQ(218, message.repeated_nested_message (0).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(0).c()); + EXPECT_EQ(220, message.repeated_import_message (0).d()); + EXPECT_EQ(220, message.repeated_import_message (0).d()); +} + +void TestUtil::ExpectLastRepeatedExtensionsReleased( + const unittest::TestAllExtensions& message) { + ASSERT_EQ(1, message.ExtensionSize(unittest::repeatedgroup_extension )); + ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_message_extension )); + ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_message_extension)); + ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_message_extension )); + ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_lazy_message_extension )); + + EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension , 0).a()); + EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb()); + EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c()); + EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d()); + EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb()); +} + void TestUtil::ExpectRepeatedsSwapped( const unittest::TestAllTypes& message) { ASSERT_EQ(2, message.repeated_int32_size ()); @@ -1869,6 +2061,7 @@ void TestUtil::ExpectRepeatedsSwapped( ASSERT_EQ(2, message.repeated_nested_message_size ()); ASSERT_EQ(2, message.repeated_foreign_message_size()); ASSERT_EQ(2, message.repeated_import_message_size ()); + ASSERT_EQ(2, message.repeated_import_message_size ()); ASSERT_EQ(2, message.repeated_nested_enum_size ()); ASSERT_EQ(2, message.repeated_foreign_enum_size ()); ASSERT_EQ(2, message.repeated_import_enum_size ()); @@ -1891,7 +2084,7 @@ void TestUtil::ExpectRepeatedsSwapped( EXPECT_EQ(210 , message.repeated_sfixed64(1)); EXPECT_EQ(211 , message.repeated_float (1)); EXPECT_EQ(212 , message.repeated_double (1)); - EXPECT_EQ(true , message.repeated_bool (1)); + EXPECT_TRUE( message.repeated_bool (1)); EXPECT_EQ("215", message.repeated_string (1)); EXPECT_EQ("216", message.repeated_bytes (1)); @@ -1899,6 +2092,7 @@ void TestUtil::ExpectRepeatedsSwapped( EXPECT_EQ(218, message.repeated_nested_message (1).bb()); EXPECT_EQ(219, message.repeated_foreign_message(1).c()); EXPECT_EQ(220, message.repeated_import_message (1).d()); + EXPECT_EQ(220, message.repeated_import_message (1).d()); EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (1)); EXPECT_EQ(unittest::FOREIGN_BAR , message.repeated_foreign_enum(1)); @@ -1916,7 +2110,7 @@ void TestUtil::ExpectRepeatedsSwapped( EXPECT_EQ(310 , message.repeated_sfixed64(0)); EXPECT_EQ(311 , message.repeated_float (0)); EXPECT_EQ(312 , message.repeated_double (0)); - EXPECT_EQ(false, message.repeated_bool (0)); + EXPECT_FALSE( message.repeated_bool (0)); EXPECT_EQ("315", message.repeated_string (0)); EXPECT_EQ("316", message.repeated_bytes (0)); @@ -1924,6 +2118,7 @@ void TestUtil::ExpectRepeatedsSwapped( EXPECT_EQ(318, message.repeated_nested_message (0).bb()); EXPECT_EQ(319, message.repeated_foreign_message(0).c()); EXPECT_EQ(320, message.repeated_import_message (0).d()); + EXPECT_EQ(320, message.repeated_import_message (0).d()); EXPECT_EQ(unittest::TestAllTypes::BAZ, message.repeated_nested_enum (0)); EXPECT_EQ(unittest::FOREIGN_BAZ , message.repeated_foreign_enum(0)); @@ -1953,6 +2148,7 @@ void TestUtil::ExpectRepeatedExtensionsSwapped( ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension)); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension )); @@ -1972,7 +2168,7 @@ void TestUtil::ExpectRepeatedExtensionsSwapped( EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension, 1)); EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension , 1)); EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension , 1)); - EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension , 1)); + EXPECT_TRUE( message.GetExtension(unittest::repeated_bool_extension , 1)); EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension , 1)); EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension , 1)); @@ -1980,6 +2176,7 @@ void TestUtil::ExpectRepeatedExtensionsSwapped( EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb()); EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c()); EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 1).d()); + EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 1).bb()); EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 1)); EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 1)); @@ -2000,7 +2197,7 @@ void TestUtil::ExpectRepeatedExtensionsSwapped( EXPECT_EQ(310 , message.GetExtension(unittest::repeated_sfixed64_extension, 0)); EXPECT_EQ(311 , message.GetExtension(unittest::repeated_float_extension , 0)); EXPECT_EQ(312 , message.GetExtension(unittest::repeated_double_extension , 0)); - EXPECT_EQ(false, message.GetExtension(unittest::repeated_bool_extension , 0)); + EXPECT_FALSE( message.GetExtension(unittest::repeated_bool_extension , 0)); EXPECT_EQ("315", message.GetExtension(unittest::repeated_string_extension , 0)); EXPECT_EQ("316", message.GetExtension(unittest::repeated_bytes_extension , 0)); @@ -2008,6 +2205,7 @@ void TestUtil::ExpectRepeatedExtensionsSwapped( EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb()); EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c()); EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension , 0).d()); + EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb()); EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::repeated_nested_enum_extension , 0)); EXPECT_EQ(unittest::FOREIGN_BAZ , message.GetExtension(unittest::repeated_foreign_enum_extension, 0)); @@ -2017,6 +2215,92 @@ void TestUtil::ExpectRepeatedExtensionsSwapped( EXPECT_EQ("325", message.GetExtension(unittest::repeated_cord_extension, 0)); } +void TestUtil::SetOneof1(unittest::TestOneof2* message) { + message->mutable_foo_lazy_message()->set_qux_int(100); + message->set_bar_string("101"); + message->set_baz_int(102); + message->set_baz_string("103"); +} + +void TestUtil::SetOneof2(unittest::TestOneof2* message) { + message->set_foo_int(200); + message->set_bar_enum(unittest::TestOneof2::BAZ); + message->set_baz_int(202); + message->set_baz_string("203"); +} + +void TestUtil::ExpectOneofSet1(const unittest::TestOneof2& message) { + ExpectAtMostOneFieldSetInOneof(message); + + EXPECT_TRUE(message.has_foo_lazy_message ()); + EXPECT_TRUE(message.foo_lazy_message().has_qux_int()); + + EXPECT_TRUE(message.has_bar_string()); + EXPECT_TRUE(message.has_baz_int ()); + EXPECT_TRUE(message.has_baz_string()); + + ASSERT_EQ(0, message.foo_lazy_message().corge_int_size()); + + EXPECT_EQ(100 , message.foo_lazy_message().qux_int()); + EXPECT_EQ("101", message.bar_string ()); + EXPECT_EQ(102 , message.baz_int ()); + EXPECT_EQ("103", message.baz_string ()); +} + +void TestUtil::ExpectOneofSet2(const unittest::TestOneof2& message) { + ExpectAtMostOneFieldSetInOneof(message); + + EXPECT_TRUE(message.has_foo_int ()); + EXPECT_TRUE(message.has_bar_enum ()); + EXPECT_TRUE(message.has_baz_int ()); + EXPECT_TRUE(message.has_baz_string()); + + EXPECT_EQ(200 , message.foo_int ()); + EXPECT_EQ(unittest::TestOneof2::BAZ, message.bar_enum ()); + EXPECT_EQ(202 , message.baz_int ()); + EXPECT_EQ("203" , message.baz_string()); +} + +void TestUtil::ExpectOneofClear(const unittest::TestOneof2& message) { + EXPECT_FALSE(message.has_foo_int()); + EXPECT_FALSE(message.has_foo_string()); + EXPECT_FALSE(message.has_foo_bytes()); + EXPECT_FALSE(message.has_foo_enum()); + EXPECT_FALSE(message.has_foo_message()); + EXPECT_FALSE(message.has_foogroup()); + EXPECT_FALSE(message.has_foo_lazy_message()); + + EXPECT_FALSE(message.has_bar_int()); + EXPECT_FALSE(message.has_bar_string()); + EXPECT_FALSE(message.has_bar_bytes()); + EXPECT_FALSE(message.has_bar_enum()); + + EXPECT_FALSE(message.has_baz_int()); + EXPECT_FALSE(message.has_baz_string()); + + EXPECT_EQ(unittest::TestOneof2::FOO_NOT_SET, message.foo_case()); + EXPECT_EQ(unittest::TestOneof2::BAR_NOT_SET, message.bar_case()); +} + +void TestUtil::ExpectAtMostOneFieldSetInOneof( + const unittest::TestOneof2& message) { + int count = 0; + if (message.has_foo_int()) count++; + if (message.has_foo_string()) count++; + if (message.has_foo_bytes()) count++; + if (message.has_foo_enum()) count++; + if (message.has_foo_message()) count++; + if (message.has_foogroup()) count++; + if (message.has_foo_lazy_message()) count++; + EXPECT_LE(count, 1); + count = 0; + if (message.has_bar_int()) count++; + if (message.has_bar_string()) count++; + if (message.has_bar_bytes()) count++; + if (message.has_bar_enum()) count++; + EXPECT_TRUE(count == 0 || count == 1); +} + // =================================================================== TestUtil::ReflectionTester::ReflectionTester( @@ -2031,6 +2315,8 @@ TestUtil::ReflectionTester::ReflectionTester( pool->FindFieldByName("protobuf_unittest.ForeignMessage.c"); import_d_ = pool->FindFieldByName("protobuf_unittest_import.ImportMessage.d"); + import_e_ = + pool->FindFieldByName("protobuf_unittest_import.PublicImportMessage.e"); nested_foo_ = pool->FindEnumValueByName("protobuf_unittest.TestAllTypes.FOO"); nested_bar_ = @@ -2067,6 +2353,7 @@ TestUtil::ReflectionTester::ReflectionTester( EXPECT_TRUE(nested_b_ != NULL); EXPECT_TRUE(foreign_c_ != NULL); EXPECT_TRUE(import_d_ != NULL); + EXPECT_TRUE(import_e_ != NULL); EXPECT_TRUE(nested_foo_ != NULL); EXPECT_TRUE(nested_bar_ != NULL); EXPECT_TRUE(nested_baz_ != NULL); @@ -2129,6 +2416,12 @@ void TestUtil::ReflectionTester::SetAllFieldsViaReflection(Message* message) { reflection->SetString(message, F("optional_string_piece"), "124"); reflection->SetString(message, F("optional_cord"), "125"); + sub_message = reflection->MutableMessage(message, F("optional_public_import_message")); + sub_message->GetReflection()->SetInt32(sub_message, import_e_, 126); + + sub_message = reflection->MutableMessage(message, F("optional_lazy_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 127); + // ----------------------------------------------------------------- reflection->AddInt32 (message, F("repeated_int32" ), 201); @@ -2155,6 +2448,8 @@ void TestUtil::ReflectionTester::SetAllFieldsViaReflection(Message* message) { sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 219); sub_message = reflection->AddMessage(message, F("repeated_import_message")); sub_message->GetReflection()->SetInt32(sub_message, import_d_, 220); + sub_message = reflection->AddMessage(message, F("repeated_lazy_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 227); reflection->AddEnum(message, F("repeated_nested_enum" ), nested_bar_); reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_bar_); @@ -2188,6 +2483,8 @@ void TestUtil::ReflectionTester::SetAllFieldsViaReflection(Message* message) { sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 319); sub_message = reflection->AddMessage(message, F("repeated_import_message")); sub_message->GetReflection()->SetInt32(sub_message, import_d_, 320); + sub_message = reflection->AddMessage(message, F("repeated_lazy_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 327); reflection->AddEnum(message, F("repeated_nested_enum" ), nested_baz_); reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_baz_); @@ -2220,6 +2517,69 @@ void TestUtil::ReflectionTester::SetAllFieldsViaReflection(Message* message) { reflection->SetString(message, F("default_string_piece"), "424"); reflection->SetString(message, F("default_cord"), "425"); + + reflection->SetUInt32(message, F("oneof_uint32" ), 601); + sub_message = reflection->MutableMessage(message, F("oneof_nested_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 602); + reflection->SetString(message, F("oneof_string"), "603"); + reflection->SetString(message, F("oneof_bytes" ), "604"); +} + +void TestUtil::ReflectionTester::SetOneofViaReflection(Message* message) { + const Descriptor* descriptor = message->GetDescriptor(); + const Reflection* reflection = message->GetReflection(); + Message* sub_message = reflection->MutableMessage( + message, descriptor->FindFieldByName("foo_lazy_message")); + sub_message->GetReflection()->SetInt64( + sub_message, + descriptor->file()->pool()->FindFieldByName( + "protobuf_unittest.TestOneof2.NestedMessage.qux_int"), + 100); + + reflection->SetString(message, + descriptor->FindFieldByName("bar_cord"), + "101"); + reflection->SetInt32(message, + descriptor->FindFieldByName("baz_int"), + 102); + reflection->SetString(message, + descriptor->FindFieldByName("baz_string"), + "103"); +} + +void TestUtil::ReflectionTester::ExpectOneofSetViaReflection( + const Message& message) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* reflection = message.GetReflection(); + string scratch; + EXPECT_TRUE(reflection->HasField( + message, descriptor->FindFieldByName("foo_lazy_message"))); + EXPECT_TRUE(reflection->HasField( + message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_TRUE(reflection->HasField( + message, descriptor->FindFieldByName("baz_int"))); + EXPECT_TRUE(reflection->HasField( + message, descriptor->FindFieldByName("baz_string"))); + + const Message* sub_message = &reflection->GetMessage( + message, descriptor->FindFieldByName("foo_lazy_message")); + EXPECT_EQ(100, sub_message->GetReflection()->GetInt64( + *sub_message, + descriptor->file()->pool()->FindFieldByName( + "protobuf_unittest.TestOneof2.NestedMessage.qux_int"))); + + EXPECT_EQ("101", reflection->GetString( + message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_EQ("101", reflection->GetStringReference( + message, descriptor->FindFieldByName("bar_cord"), &scratch)); + + EXPECT_EQ(102, reflection->GetInt32( + message, descriptor->FindFieldByName("baz_int"))); + + EXPECT_EQ("103", reflection->GetString( + message, descriptor->FindFieldByName("baz_string"))); + EXPECT_EQ("103", reflection->GetStringReference( + message, descriptor->FindFieldByName("baz_string"), &scratch)); } void TestUtil::ReflectionTester::SetPackedFieldsViaReflection( @@ -2289,10 +2649,12 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1( EXPECT_TRUE(reflection->HasField(message, F("optional_string" ))); EXPECT_TRUE(reflection->HasField(message, F("optional_bytes" ))); - EXPECT_TRUE(reflection->HasField(message, F("optionalgroup" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_nested_message" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_message"))); - EXPECT_TRUE(reflection->HasField(message, F("optional_import_message" ))); + EXPECT_TRUE(reflection->HasField(message, F("optionalgroup" ))); + EXPECT_TRUE(reflection->HasField(message, F("optional_nested_message" ))); + EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_message" ))); + EXPECT_TRUE(reflection->HasField(message, F("optional_import_message" ))); + EXPECT_TRUE(reflection->HasField(message, F("optional_public_import_message"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_lazy_message" ))); sub_message = &reflection->GetMessage(message, F("optionalgroup")); EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, group_a_)); @@ -2302,6 +2664,10 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1( EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, foreign_c_)); sub_message = &reflection->GetMessage(message, F("optional_import_message")); EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_d_)); + sub_message = &reflection->GetMessage(message, F("optional_public_import_message")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_e_)); + sub_message = &reflection->GetMessage(message, F("optional_lazy_message")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); EXPECT_TRUE(reflection->HasField(message, F("optional_nested_enum" ))); EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_enum"))); @@ -2322,7 +2688,7 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1( EXPECT_EQ(110 , reflection->GetInt64 (message, F("optional_sfixed64"))); EXPECT_EQ(111 , reflection->GetFloat (message, F("optional_float" ))); EXPECT_EQ(112 , reflection->GetDouble(message, F("optional_double" ))); - EXPECT_EQ(true , reflection->GetBool (message, F("optional_bool" ))); + EXPECT_TRUE( reflection->GetBool (message, F("optional_bool" ))); EXPECT_EQ("115", reflection->GetString(message, F("optional_string" ))); EXPECT_EQ("116", reflection->GetString(message, F("optional_bytes" ))); @@ -2337,6 +2703,10 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1( EXPECT_EQ(119, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); sub_message = &reflection->GetMessage(message, F("optional_import_message")); EXPECT_EQ(120, sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); + sub_message = &reflection->GetMessage(message, F("optional_public_import_message")); + EXPECT_EQ(126, sub_message->GetReflection()->GetInt32(*sub_message, import_e_)); + sub_message = &reflection->GetMessage(message, F("optional_lazy_message")); + EXPECT_EQ(127, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); EXPECT_EQ( nested_baz_, reflection->GetEnum(message, F("optional_nested_enum" ))); EXPECT_EQ(foreign_baz_, reflection->GetEnum(message, F("optional_foreign_enum"))); @@ -2347,6 +2717,21 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1( EXPECT_EQ("125", reflection->GetString(message, F("optional_cord"))); EXPECT_EQ("125", reflection->GetStringReference(message, F("optional_cord"), &scratch)); + + EXPECT_TRUE(reflection->HasField(message, F("oneof_bytes" ))); + EXPECT_EQ("604", reflection->GetString(message, F("oneof_bytes" ))); + + if (base_descriptor_->name() == "TestAllTypes") { + EXPECT_FALSE(reflection->HasField(message, F("oneof_uint32"))); + EXPECT_FALSE(reflection->HasField(message, F("oneof_string"))); + } else { + EXPECT_TRUE(reflection->HasField(message, F("oneof_uint32"))); + EXPECT_TRUE(reflection->HasField(message, F("oneof_string"))); + EXPECT_EQ(601 , reflection->GetUInt32(message, F("oneof_uint32"))); + EXPECT_EQ("603", reflection->GetString(message, F("oneof_string"))); + sub_message = &reflection->GetMessage(message, F("oneof_nested_message")); + EXPECT_EQ(602, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + } } void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2( @@ -2377,6 +2762,7 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2( ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_message" ))); ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_message"))); ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_message" ))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_lazy_message" ))); ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_enum" ))); ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_enum" ))); ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_enum" ))); @@ -2396,7 +2782,7 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2( EXPECT_EQ(210 , reflection->GetRepeatedInt64 (message, F("repeated_sfixed64"), 0)); EXPECT_EQ(211 , reflection->GetRepeatedFloat (message, F("repeated_float" ), 0)); EXPECT_EQ(212 , reflection->GetRepeatedDouble(message, F("repeated_double" ), 0)); - EXPECT_EQ(true , reflection->GetRepeatedBool (message, F("repeated_bool" ), 0)); + EXPECT_TRUE( reflection->GetRepeatedBool (message, F("repeated_bool" ), 0)); EXPECT_EQ("215", reflection->GetRepeatedString(message, F("repeated_string" ), 0)); EXPECT_EQ("216", reflection->GetRepeatedString(message, F("repeated_bytes" ), 0)); @@ -2411,6 +2797,8 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2( EXPECT_EQ(219, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); sub_message = &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 0); EXPECT_EQ(220, sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); + sub_message = &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 0); + EXPECT_EQ(227, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); EXPECT_EQ( nested_bar_, reflection->GetRepeatedEnum(message, F("repeated_nested_enum" ),0)); EXPECT_EQ(foreign_bar_, reflection->GetRepeatedEnum(message, F("repeated_foreign_enum"),0)); @@ -2436,7 +2824,7 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2( EXPECT_EQ(310 , reflection->GetRepeatedInt64 (message, F("repeated_sfixed64"), 1)); EXPECT_EQ(311 , reflection->GetRepeatedFloat (message, F("repeated_float" ), 1)); EXPECT_EQ(312 , reflection->GetRepeatedDouble(message, F("repeated_double" ), 1)); - EXPECT_EQ(false, reflection->GetRepeatedBool (message, F("repeated_bool" ), 1)); + EXPECT_FALSE( reflection->GetRepeatedBool (message, F("repeated_bool" ), 1)); EXPECT_EQ("315", reflection->GetRepeatedString(message, F("repeated_string" ), 1)); EXPECT_EQ("316", reflection->GetRepeatedString(message, F("repeated_bytes" ), 1)); @@ -2453,6 +2841,8 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2( EXPECT_EQ(319, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); sub_message = &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 1); EXPECT_EQ(320, sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); + sub_message = &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 1); + EXPECT_EQ(327, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); EXPECT_EQ( nested_baz_, reflection->GetRepeatedEnum(message, F("repeated_nested_enum" ),1)); EXPECT_EQ(foreign_baz_, reflection->GetRepeatedEnum(message, F("repeated_foreign_enum"),1)); @@ -2509,7 +2899,7 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection3( EXPECT_EQ(410 , reflection->GetInt64 (message, F("default_sfixed64"))); EXPECT_EQ(411 , reflection->GetFloat (message, F("default_float" ))); EXPECT_EQ(412 , reflection->GetDouble(message, F("default_double" ))); - EXPECT_EQ(false, reflection->GetBool (message, F("default_bool" ))); + EXPECT_FALSE( reflection->GetBool (message, F("default_bool" ))); EXPECT_EQ("415", reflection->GetString(message, F("default_string" ))); EXPECT_EQ("416", reflection->GetString(message, F("default_bytes" ))); @@ -2559,7 +2949,7 @@ void TestUtil::ReflectionTester::ExpectPackedFieldsSetViaReflection( EXPECT_EQ(610 , reflection->GetRepeatedInt64 (message, F("packed_sfixed64"), 0)); EXPECT_EQ(611 , reflection->GetRepeatedFloat (message, F("packed_float" ), 0)); EXPECT_EQ(612 , reflection->GetRepeatedDouble(message, F("packed_double" ), 0)); - EXPECT_EQ(true , reflection->GetRepeatedBool (message, F("packed_bool" ), 0)); + EXPECT_TRUE( reflection->GetRepeatedBool (message, F("packed_bool" ), 0)); EXPECT_EQ(foreign_bar_, reflection->GetRepeatedEnum(message, F("packed_enum"), 0)); @@ -2575,7 +2965,7 @@ void TestUtil::ReflectionTester::ExpectPackedFieldsSetViaReflection( EXPECT_EQ(710 , reflection->GetRepeatedInt64 (message, F("packed_sfixed64"), 1)); EXPECT_EQ(711 , reflection->GetRepeatedFloat (message, F("packed_float" ), 1)); EXPECT_EQ(712 , reflection->GetRepeatedDouble(message, F("packed_double" ), 1)); - EXPECT_EQ(false, reflection->GetRepeatedBool (message, F("packed_bool" ), 1)); + EXPECT_FALSE( reflection->GetRepeatedBool (message, F("packed_bool" ), 1)); EXPECT_EQ(foreign_baz_, reflection->GetRepeatedEnum(message, F("packed_enum"), 1)); } @@ -2609,6 +2999,8 @@ void TestUtil::ReflectionTester::ExpectClearViaReflection( EXPECT_FALSE(reflection->HasField(message, F("optional_nested_message" ))); EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_message"))); EXPECT_FALSE(reflection->HasField(message, F("optional_import_message" ))); + EXPECT_FALSE(reflection->HasField(message, F("optional_public_import_message"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_lazy_message"))); EXPECT_FALSE(reflection->HasField(message, F("optional_nested_enum" ))); EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_enum"))); @@ -2630,7 +3022,7 @@ void TestUtil::ReflectionTester::ExpectClearViaReflection( EXPECT_EQ(0 , reflection->GetInt64 (message, F("optional_sfixed64"))); EXPECT_EQ(0 , reflection->GetFloat (message, F("optional_float" ))); EXPECT_EQ(0 , reflection->GetDouble(message, F("optional_double" ))); - EXPECT_EQ(false, reflection->GetBool (message, F("optional_bool" ))); + EXPECT_FALSE( reflection->GetBool (message, F("optional_bool" ))); EXPECT_EQ("" , reflection->GetString(message, F("optional_string" ))); EXPECT_EQ("" , reflection->GetString(message, F("optional_bytes" ))); @@ -2650,6 +3042,12 @@ void TestUtil::ReflectionTester::ExpectClearViaReflection( sub_message = &reflection->GetMessage(message, F("optional_import_message")); EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_d_)); EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); + sub_message = &reflection->GetMessage(message, F("optional_public_import_message")); + EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_e_)); + EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_e_)); + sub_message = &reflection->GetMessage(message, F("optional_lazy_message")); + EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); + EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); // Enums without defaults are set to the first value in the enum. EXPECT_EQ( nested_foo_, reflection->GetEnum(message, F("optional_nested_enum" ))); @@ -2683,6 +3081,7 @@ void TestUtil::ReflectionTester::ExpectClearViaReflection( EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_message" ))); EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_message"))); EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_message" ))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_lazy_message" ))); EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_enum" ))); EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_enum" ))); EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_enum" ))); @@ -2727,7 +3126,7 @@ void TestUtil::ReflectionTester::ExpectClearViaReflection( EXPECT_EQ(-50 , reflection->GetInt64 (message, F("default_sfixed64"))); EXPECT_EQ( 51.5 , reflection->GetFloat (message, F("default_float" ))); EXPECT_EQ( 52e3 , reflection->GetDouble(message, F("default_double" ))); - EXPECT_EQ(true , reflection->GetBool (message, F("default_bool" ))); + EXPECT_TRUE( reflection->GetBool (message, F("default_bool" ))); EXPECT_EQ("hello", reflection->GetString(message, F("default_string" ))); EXPECT_EQ("world", reflection->GetString(message, F("default_bytes" ))); @@ -2796,6 +3195,8 @@ void TestUtil::ReflectionTester::ModifyRepeatedFieldsViaReflection( sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 519); sub_message = reflection->MutableRepeatedMessage(message, F("repeated_import_message"), 1); sub_message->GetReflection()->SetInt32(sub_message, import_d_, 520); + sub_message = reflection->MutableRepeatedMessage(message, F("repeated_lazy_message"), 1); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 527); reflection->SetRepeatedEnum(message, F("repeated_nested_enum" ), 1, nested_foo_); reflection->SetRepeatedEnum(message, F("repeated_foreign_enum"), 1, foreign_foo_); @@ -2824,7 +3225,8 @@ void TestUtil::ReflectionTester::ModifyPackedFieldsViaReflection( reflection->SetRepeatedEnum (message, F("packed_enum" ), 1, foreign_foo_); } -void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection(Message* message) { +void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection( + Message* message) { const Reflection* reflection = message->GetReflection(); vector output; @@ -2837,6 +3239,26 @@ void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection(Message* messa } } +void TestUtil::ReflectionTester::ReleaseLastRepeatedsViaReflection( + Message* message, bool expect_extensions_notnull) { + const Reflection* reflection = message->GetReflection(); + + vector output; + reflection->ListFields(*message, &output); + for (int i=0; iis_repeated()) continue; + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; + + Message* released = reflection->ReleaseLast(message, field); + if (!field->is_extension() || expect_extensions_notnull) { + ASSERT_TRUE(released != NULL) << "ReleaseLast returned NULL for: " + << field->name(); + } + delete released; + } +} + void TestUtil::ReflectionTester::SwapRepeatedsViaReflection(Message* message) { const Reflection* reflection = message->GetReflection(); @@ -2850,5 +3272,74 @@ void TestUtil::ReflectionTester::SwapRepeatedsViaReflection(Message* message) { } } +void TestUtil::ReflectionTester:: +SetAllocatedOptionalMessageFieldsToNullViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + + vector fields; + reflection->ListFields(*message, &fields); + + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + if (!field->is_optional() || + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; + + reflection->SetAllocatedMessage(message, NULL, field); + } +} + +void TestUtil::ReflectionTester:: +SetAllocatedOptionalMessageFieldsToMessageViaReflection( + Message* from_message, + Message* to_message) { + EXPECT_EQ(from_message->GetDescriptor(), to_message->GetDescriptor()); + const Reflection* from_reflection = from_message->GetReflection(); + const Reflection* to_reflection = to_message->GetReflection(); + + vector fields; + from_reflection->ListFields(*from_message, &fields); + + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + if (!field->is_optional() || + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; + + Message* sub_message = + from_reflection->ReleaseMessage(from_message, field); + to_reflection->SetAllocatedMessage(to_message, sub_message, field); + } +} + +void TestUtil::ReflectionTester::ExpectMessagesReleasedViaReflection( + Message* message, + TestUtil::ReflectionTester::MessageReleaseState expected_release_state) { + const Reflection* reflection = message->GetReflection(); + + static const char* fields[] = { + "optionalgroup", + "optional_nested_message", + "optional_foreign_message", + "optional_import_message", + }; + for (int i = 0; i < GOOGLE_ARRAYSIZE(fields); i++) { + const Message& sub_message = reflection->GetMessage(*message, F(fields[i])); + Message* released = reflection->ReleaseMessage(message, F(fields[i])); + switch (expected_release_state) { + case IS_NULL: + EXPECT_TRUE(released == NULL); + break; + case NOT_NULL: + EXPECT_TRUE(released != NULL); + EXPECT_EQ(&sub_message, released); + break; + case CAN_BE_NULL: + break; + } + delete released; + EXPECT_FALSE(reflection->HasField(*message, F(fields[i]))); + } +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h index 25165f3..6e2d552 100644 --- a/src/google/protobuf/test_util.h +++ b/src/google/protobuf/test_util.h @@ -43,18 +43,26 @@ namespace google { namespace protobuf { -namespace unittest = protobuf_unittest; +namespace unittest = ::protobuf_unittest; namespace unittest_import = protobuf_unittest_import; class TestUtil { public: // Set every field in the message to a unique value. static void SetAllFields(unittest::TestAllTypes* message); + static void SetOptionalFields(unittest::TestAllTypes* message); + static void AddRepeatedFields1(unittest::TestAllTypes* message); + static void AddRepeatedFields2(unittest::TestAllTypes* message); + static void SetDefaultFields(unittest::TestAllTypes* message); + static void SetOneofFields(unittest::TestAllTypes* message); static void SetAllExtensions(unittest::TestAllExtensions* message); + static void SetOneofFields(unittest::TestAllExtensions* message); static void SetAllFieldsAndExtensions(unittest::TestFieldOrderings* message); static void SetPackedFields(unittest::TestPackedTypes* message); static void SetPackedExtensions(unittest::TestPackedExtensions* message); static void SetUnpackedFields(unittest::TestUnpackedTypes* message); + static void SetOneof1(unittest::TestOneof2* message); + static void SetOneof2(unittest::TestOneof2* message); // Use the repeated versions of the set_*() accessors to modify all the // repeated fields of the messsage (which should already have been @@ -75,6 +83,10 @@ class TestUtil { const unittest::TestPackedExtensions& message); static void ExpectUnpackedFieldsSet( const unittest::TestUnpackedTypes& message); + static void ExpectUnpackedExtensionsSet( + const unittest::TestUnpackedExtensions& message); + static void ExpectOneofSet1(const unittest::TestOneof2& message); + static void ExpectOneofSet2(const unittest::TestOneof2& message); // Expect that the message is modified as would be expected from // Modify*Fields(). @@ -93,6 +105,7 @@ class TestUtil { static void ExpectPackedClear(const unittest::TestPackedTypes& message); static void ExpectPackedExtensionsClear( const unittest::TestPackedExtensions& message); + static void ExpectOneofClear(const unittest::TestOneof2& message); // Check that the passed-in serialization is the canonical serialization we // expect for a TestFieldOrderings message filled in by @@ -104,6 +117,10 @@ class TestUtil { const unittest::TestAllTypes& message); static void ExpectLastRepeatedExtensionsRemoved( const unittest::TestAllExtensions& message); + static void ExpectLastRepeatedsReleased( + const unittest::TestAllTypes& message); + static void ExpectLastRepeatedExtensionsReleased( + const unittest::TestAllExtensions& message); // Check that all repeated fields have had their first and last elements // swapped. @@ -111,6 +128,9 @@ class TestUtil { static void ExpectRepeatedExtensionsSwapped( const unittest::TestAllExtensions& message); + static void ExpectAtMostOneFieldSetInOneof( + const unittest::TestOneof2 &message); + // Like above, but use the reflection interface. class ReflectionTester { public: @@ -132,7 +152,27 @@ class TestUtil { void ExpectPackedClearViaReflection(const Message& message); void RemoveLastRepeatedsViaReflection(Message* message); + void ReleaseLastRepeatedsViaReflection( + Message* message, bool expect_extensions_notnull); void SwapRepeatedsViaReflection(Message* message); + void SetAllocatedOptionalMessageFieldsToNullViaReflection( + Message* message); + static void SetAllocatedOptionalMessageFieldsToMessageViaReflection( + Message* from_message, + Message* to_message); + + enum MessageReleaseState { + IS_NULL, + CAN_BE_NULL, + NOT_NULL, + }; + void ExpectMessagesReleasedViaReflection( + Message* message, MessageReleaseState expected_release_state); + + // Set and check functions for TestOneof2 messages. No need to construct + // the ReflectionTester by TestAllTypes nor TestAllExtensions. + static void SetOneofViaReflection(Message* message); + static void ExpectOneofSetViaReflection(const Message& message); private: const FieldDescriptor* F(const string& name); @@ -144,6 +184,7 @@ class TestUtil { const FieldDescriptor* nested_b_; const FieldDescriptor* foreign_c_; const FieldDescriptor* import_d_; + const FieldDescriptor* import_e_; const EnumValueDescriptor* nested_foo_; const EnumValueDescriptor* nested_bar_; diff --git a/src/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc index d7140e0..cbf808b 100644 --- a/src/google/protobuf/test_util_lite.cc +++ b/src/google/protobuf/test_util_lite.cc @@ -62,10 +62,12 @@ void TestUtilLite::SetAllFields(unittest::TestAllTypesLite* message) { message->set_optional_string ("115"); message->set_optional_bytes ("116"); - message->mutable_optionalgroup ()->set_a(117); - message->mutable_optional_nested_message ()->set_bb(118); - message->mutable_optional_foreign_message()->set_c(119); - message->mutable_optional_import_message ()->set_d(120); + message->mutable_optionalgroup ()->set_a(117); + message->mutable_optional_nested_message ()->set_bb(118); + message->mutable_optional_foreign_message ()->set_c(119); + message->mutable_optional_import_message ()->set_d(120); + message->mutable_optional_public_import_message()->set_e(126); + message->mutable_optional_lazy_message ()->set_bb(127); message->set_optional_nested_enum (unittest::TestAllTypesLite::BAZ ); message->set_optional_foreign_enum(unittest::FOREIGN_LITE_BAZ ); @@ -94,6 +96,7 @@ void TestUtilLite::SetAllFields(unittest::TestAllTypesLite* message) { message->add_repeated_nested_message ()->set_bb(218); message->add_repeated_foreign_message()->set_c(219); message->add_repeated_import_message ()->set_d(220); + message->add_repeated_lazy_message ()->set_bb(227); message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAR ); message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAR ); @@ -121,6 +124,7 @@ void TestUtilLite::SetAllFields(unittest::TestAllTypesLite* message) { message->add_repeated_nested_message ()->set_bb(318); message->add_repeated_foreign_message()->set_c(319); message->add_repeated_import_message ()->set_d(320); + message->add_repeated_lazy_message ()->set_bb(327); message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAZ ); message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAZ ); @@ -149,6 +153,11 @@ void TestUtilLite::SetAllFields(unittest::TestAllTypesLite* message) { message->set_default_foreign_enum(unittest::FOREIGN_LITE_FOO ); message->set_default_import_enum (unittest_import::IMPORT_LITE_FOO); + + message->set_oneof_uint32(601); + message->mutable_oneof_nested_message()->set_bb(602); + message->set_oneof_string("603"); + message->set_oneof_bytes("604"); } // ------------------------------------------------------------------- @@ -174,6 +183,7 @@ void TestUtilLite::ModifyRepeatedFields(unittest::TestAllTypesLite* message) { message->mutable_repeated_nested_message (1)->set_bb(518); message->mutable_repeated_foreign_message(1)->set_c(519); message->mutable_repeated_import_message (1)->set_d(520); + message->mutable_repeated_lazy_message (1)->set_bb(527); message->set_repeated_nested_enum (1, unittest::TestAllTypesLite::FOO ); message->set_repeated_foreign_enum(1, unittest::FOREIGN_LITE_FOO ); @@ -201,15 +211,19 @@ void TestUtilLite::ExpectAllFieldsSet( EXPECT_TRUE(message.has_optional_string ()); EXPECT_TRUE(message.has_optional_bytes ()); - EXPECT_TRUE(message.has_optionalgroup ()); - EXPECT_TRUE(message.has_optional_nested_message ()); - EXPECT_TRUE(message.has_optional_foreign_message()); - EXPECT_TRUE(message.has_optional_import_message ()); + EXPECT_TRUE(message.has_optionalgroup ()); + EXPECT_TRUE(message.has_optional_nested_message ()); + EXPECT_TRUE(message.has_optional_foreign_message ()); + EXPECT_TRUE(message.has_optional_import_message ()); + EXPECT_TRUE(message.has_optional_public_import_message()); + EXPECT_TRUE(message.has_optional_lazy_message ()); - EXPECT_TRUE(message.optionalgroup ().has_a()); - EXPECT_TRUE(message.optional_nested_message ().has_bb()); - EXPECT_TRUE(message.optional_foreign_message().has_c()); - EXPECT_TRUE(message.optional_import_message ().has_d()); + EXPECT_TRUE(message.optionalgroup ().has_a()); + EXPECT_TRUE(message.optional_nested_message ().has_bb()); + EXPECT_TRUE(message.optional_foreign_message ().has_c()); + EXPECT_TRUE(message.optional_import_message ().has_d()); + EXPECT_TRUE(message.optional_public_import_message().has_e()); + EXPECT_TRUE(message.optional_lazy_message ().has_bb()); EXPECT_TRUE(message.has_optional_nested_enum ()); EXPECT_TRUE(message.has_optional_foreign_enum()); @@ -232,10 +246,12 @@ void TestUtilLite::ExpectAllFieldsSet( EXPECT_EQ("115", message.optional_string ()); EXPECT_EQ("116", message.optional_bytes ()); - EXPECT_EQ(117, message.optionalgroup ().a()); - EXPECT_EQ(118, message.optional_nested_message ().bb()); - EXPECT_EQ(119, message.optional_foreign_message().c()); - EXPECT_EQ(120, message.optional_import_message ().d()); + EXPECT_EQ(117, message.optionalgroup ().a()); + EXPECT_EQ(118, message.optional_nested_message ().bb()); + EXPECT_EQ(119, message.optional_foreign_message ().c()); + EXPECT_EQ(120, message.optional_import_message ().d()); + EXPECT_EQ(126, message.optional_public_import_message().e()); + EXPECT_EQ(127, message.optional_lazy_message ().bb()); EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.optional_nested_enum ()); EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.optional_foreign_enum()); @@ -264,6 +280,7 @@ void TestUtilLite::ExpectAllFieldsSet( ASSERT_EQ(2, message.repeated_nested_message_size ()); ASSERT_EQ(2, message.repeated_foreign_message_size()); ASSERT_EQ(2, message.repeated_import_message_size ()); + ASSERT_EQ(2, message.repeated_lazy_message_size ()); ASSERT_EQ(2, message.repeated_nested_enum_size ()); ASSERT_EQ(2, message.repeated_foreign_enum_size ()); ASSERT_EQ(2, message.repeated_import_enum_size ()); @@ -289,6 +306,7 @@ void TestUtilLite::ExpectAllFieldsSet( EXPECT_EQ(218, message.repeated_nested_message (0).bb()); EXPECT_EQ(219, message.repeated_foreign_message(0).c()); EXPECT_EQ(220, message.repeated_import_message (0).d()); + EXPECT_EQ(227, message.repeated_lazy_message (0).bb()); EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0)); @@ -315,6 +333,7 @@ void TestUtilLite::ExpectAllFieldsSet( EXPECT_EQ(318, message.repeated_nested_message (1).bb()); EXPECT_EQ(319, message.repeated_foreign_message(1).c()); EXPECT_EQ(320, message.repeated_import_message (1).d()); + EXPECT_EQ(327, message.repeated_lazy_message (1).bb()); EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.repeated_nested_enum (1)); EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.repeated_foreign_enum(1)); @@ -364,6 +383,13 @@ void TestUtilLite::ExpectAllFieldsSet( EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.default_foreign_enum()); EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.default_import_enum ()); + + EXPECT_FALSE(message.has_oneof_uint32 ()); + EXPECT_FALSE(message.has_oneof_nested_message()); + EXPECT_FALSE(message.has_oneof_string ()); + EXPECT_TRUE(message.has_oneof_bytes ()); + + EXPECT_EQ("604", message.oneof_bytes()); } // ------------------------------------------------------------------- @@ -386,10 +412,12 @@ void TestUtilLite::ExpectClear(const unittest::TestAllTypesLite& message) { EXPECT_FALSE(message.has_optional_string ()); EXPECT_FALSE(message.has_optional_bytes ()); - EXPECT_FALSE(message.has_optionalgroup ()); - EXPECT_FALSE(message.has_optional_nested_message ()); - EXPECT_FALSE(message.has_optional_foreign_message()); - EXPECT_FALSE(message.has_optional_import_message ()); + EXPECT_FALSE(message.has_optionalgroup ()); + EXPECT_FALSE(message.has_optional_nested_message ()); + EXPECT_FALSE(message.has_optional_foreign_message ()); + EXPECT_FALSE(message.has_optional_import_message ()); + EXPECT_FALSE(message.has_optional_public_import_message()); + EXPECT_FALSE(message.has_optional_lazy_message ()); EXPECT_FALSE(message.has_optional_nested_enum ()); EXPECT_FALSE(message.has_optional_foreign_enum()); @@ -414,10 +442,12 @@ void TestUtilLite::ExpectClear(const unittest::TestAllTypesLite& message) { EXPECT_EQ("" , message.optional_bytes ()); // Embedded messages should also be clear. - EXPECT_FALSE(message.optionalgroup ().has_a()); - EXPECT_FALSE(message.optional_nested_message ().has_bb()); - EXPECT_FALSE(message.optional_foreign_message().has_c()); - EXPECT_FALSE(message.optional_import_message ().has_d()); + EXPECT_FALSE(message.optionalgroup ().has_a()); + EXPECT_FALSE(message.optional_nested_message ().has_bb()); + EXPECT_FALSE(message.optional_foreign_message ().has_c()); + EXPECT_FALSE(message.optional_import_message ().has_d()); + EXPECT_FALSE(message.optional_public_import_message().has_e()); + EXPECT_FALSE(message.optional_lazy_message ().has_bb()); EXPECT_EQ(0, message.optionalgroup ().a()); EXPECT_EQ(0, message.optional_nested_message ().bb()); @@ -451,6 +481,7 @@ void TestUtilLite::ExpectClear(const unittest::TestAllTypesLite& message) { EXPECT_EQ(0, message.repeated_nested_message_size ()); EXPECT_EQ(0, message.repeated_foreign_message_size()); EXPECT_EQ(0, message.repeated_import_message_size ()); + EXPECT_EQ(0, message.repeated_lazy_message_size ()); EXPECT_EQ(0, message.repeated_nested_enum_size ()); EXPECT_EQ(0, message.repeated_foreign_enum_size ()); EXPECT_EQ(0, message.repeated_import_enum_size ()); @@ -499,6 +530,11 @@ void TestUtilLite::ExpectClear(const unittest::TestAllTypesLite& message) { EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.default_foreign_enum()); EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.default_import_enum ()); + + EXPECT_FALSE(message.has_oneof_uint32 ()); + EXPECT_FALSE(message.has_oneof_nested_message()); + EXPECT_FALSE(message.has_oneof_string ()); + EXPECT_FALSE(message.has_oneof_bytes ()); } // ------------------------------------------------------------------- @@ -528,6 +564,7 @@ void TestUtilLite::ExpectRepeatedFieldsModified( ASSERT_EQ(2, message.repeated_nested_message_size ()); ASSERT_EQ(2, message.repeated_foreign_message_size()); ASSERT_EQ(2, message.repeated_import_message_size ()); + ASSERT_EQ(2, message.repeated_lazy_message_size ()); ASSERT_EQ(2, message.repeated_nested_enum_size ()); ASSERT_EQ(2, message.repeated_foreign_enum_size ()); ASSERT_EQ(2, message.repeated_import_enum_size ()); @@ -553,6 +590,7 @@ void TestUtilLite::ExpectRepeatedFieldsModified( EXPECT_EQ(218, message.repeated_nested_message (0).bb()); EXPECT_EQ(219, message.repeated_foreign_message(0).c()); EXPECT_EQ(220, message.repeated_import_message (0).d()); + EXPECT_EQ(227, message.repeated_lazy_message (0).bb()); EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0)); EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.repeated_foreign_enum(0)); @@ -580,6 +618,7 @@ void TestUtilLite::ExpectRepeatedFieldsModified( EXPECT_EQ(518, message.repeated_nested_message (1).bb()); EXPECT_EQ(519, message.repeated_foreign_message(1).c()); EXPECT_EQ(520, message.repeated_import_message (1).d()); + EXPECT_EQ(527, message.repeated_lazy_message (1).bb()); EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.repeated_nested_enum (1)); EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.repeated_foreign_enum(1)); @@ -787,10 +826,12 @@ void TestUtilLite::SetAllExtensions(unittest::TestAllExtensionsLite* message) { message->SetExtension(unittest::optional_string_extension_lite , "115"); message->SetExtension(unittest::optional_bytes_extension_lite , "116"); - message->MutableExtension(unittest::optionalgroup_extension_lite )->set_a(117); - message->MutableExtension(unittest::optional_nested_message_extension_lite )->set_bb(118); - message->MutableExtension(unittest::optional_foreign_message_extension_lite)->set_c(119); - message->MutableExtension(unittest::optional_import_message_extension_lite )->set_d(120); + message->MutableExtension(unittest::optionalgroup_extension_lite )->set_a(117); + message->MutableExtension(unittest::optional_nested_message_extension_lite )->set_bb(118); + message->MutableExtension(unittest::optional_foreign_message_extension_lite )->set_c(119); + message->MutableExtension(unittest::optional_import_message_extension_lite )->set_d(120); + message->MutableExtension(unittest::optional_public_import_message_extension_lite)->set_e(126); + message->MutableExtension(unittest::optional_lazy_message_extension_lite )->set_bb(127); message->SetExtension(unittest::optional_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ ); message->SetExtension(unittest::optional_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ ); @@ -819,6 +860,7 @@ void TestUtilLite::SetAllExtensions(unittest::TestAllExtensionsLite* message) { message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(218); message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(219); message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(220); + message->AddExtension(unittest::repeated_lazy_message_extension_lite )->set_bb(227); message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAR ); message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAR ); @@ -846,6 +888,7 @@ void TestUtilLite::SetAllExtensions(unittest::TestAllExtensionsLite* message) { message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(318); message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(319); message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(320); + message->AddExtension(unittest::repeated_lazy_message_extension_lite )->set_bb(327); message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ ); message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ ); @@ -874,6 +917,11 @@ void TestUtilLite::SetAllExtensions(unittest::TestAllExtensionsLite* message) { message->SetExtension(unittest::default_foreign_enum_extension_lite, unittest::FOREIGN_LITE_FOO ); message->SetExtension(unittest::default_import_enum_extension_lite , unittest_import::IMPORT_LITE_FOO); + + message->SetExtension(unittest::oneof_uint32_extension_lite, 601); + message->MutableExtension(unittest::oneof_nested_message_extension_lite)->set_bb(602);; + message->SetExtension(unittest::oneof_string_extension_lite, "603"); + message->SetExtension(unittest::oneof_bytes_extension_lite, "604"); } // ------------------------------------------------------------------- @@ -900,6 +948,7 @@ void TestUtilLite::ModifyRepeatedExtensions( message->MutableExtension(unittest::repeated_nested_message_extension_lite , 1)->set_bb(518); message->MutableExtension(unittest::repeated_foreign_message_extension_lite, 1)->set_c(519); message->MutableExtension(unittest::repeated_import_message_extension_lite , 1)->set_d(520); + message->MutableExtension(unittest::repeated_lazy_message_extension_lite , 1)->set_bb(527); message->SetExtension(unittest::repeated_nested_enum_extension_lite , 1, unittest::TestAllTypesLite::FOO ); message->SetExtension(unittest::repeated_foreign_enum_extension_lite, 1, unittest::FOREIGN_LITE_FOO ); @@ -927,15 +976,19 @@ void TestUtilLite::ExpectAllExtensionsSet( EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension_lite )); EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension_lite)); - EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_public_import_message_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_lazy_message_extension_lite )); - EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a()); - EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb()); - EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension_lite).has_c()); - EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d()); + EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a()); + EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb()); + EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension_lite ).has_c()); + EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d()); + EXPECT_TRUE(message.GetExtension(unittest::optional_public_import_message_extension_lite).has_e()); + EXPECT_TRUE(message.GetExtension(unittest::optional_lazy_message_extension_lite ).has_bb()); EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension_lite )); EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension_lite)); @@ -958,10 +1011,12 @@ void TestUtilLite::ExpectAllExtensionsSet( EXPECT_EQ("115", message.GetExtension(unittest::optional_string_extension_lite )); EXPECT_EQ("116", message.GetExtension(unittest::optional_bytes_extension_lite )); - EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension_lite ).a()); - EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb()); - EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension_lite).c()); - EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension_lite ).d()); + EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension_lite ).a()); + EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb()); + EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension_lite ).c()); + EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension_lite ).d()); + EXPECT_EQ(126, message.GetExtension(unittest::optional_public_import_message_extension_lite).e()); + EXPECT_EQ(127, message.GetExtension(unittest::optional_lazy_message_extension_lite ).bb()); EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::optional_nested_enum_extension_lite )); EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.GetExtension(unittest::optional_foreign_enum_extension_lite)); @@ -990,6 +1045,7 @@ void TestUtilLite::ExpectAllExtensionsSet( ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite)); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite )); @@ -1015,6 +1071,7 @@ void TestUtilLite::ExpectAllExtensionsSet( EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb()); EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c()); EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d()); + EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 0).bb()); EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0)); EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0)); @@ -1041,6 +1098,7 @@ void TestUtilLite::ExpectAllExtensionsSet( EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb()); EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c()); EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d()); + EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 1).bb()); EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1)); EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1)); @@ -1090,6 +1148,16 @@ void TestUtilLite::ExpectAllExtensionsSet( EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::default_foreign_enum_extension_lite)); EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::default_import_enum_extension_lite )); + + EXPECT_TRUE(message.HasExtension(unittest::oneof_uint32_extension_lite)); + EXPECT_TRUE(message.GetExtension(unittest::oneof_nested_message_extension_lite).has_bb()); + EXPECT_TRUE(message.HasExtension(unittest::oneof_string_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::oneof_bytes_extension_lite)); + + EXPECT_EQ(601, message.GetExtension(unittest::oneof_uint32_extension_lite)); + EXPECT_EQ(602, message.GetExtension(unittest::oneof_nested_message_extension_lite).bb()); + EXPECT_EQ("603", message.GetExtension(unittest::oneof_string_extension_lite)); + EXPECT_EQ("604", message.GetExtension(unittest::oneof_bytes_extension_lite)); } // ------------------------------------------------------------------- @@ -1118,10 +1186,12 @@ void TestUtilLite::ExpectExtensionsClear( EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension_lite )); EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension_lite)); - EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_public_import_message_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_lazy_message_extension_lite )); EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension_lite )); EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension_lite)); @@ -1146,15 +1216,19 @@ void TestUtilLite::ExpectExtensionsClear( EXPECT_EQ("" , message.GetExtension(unittest::optional_bytes_extension_lite )); // Embedded messages should also be clear. - EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a()); - EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb()); - EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension_lite).has_c()); - EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d()); - - EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension_lite ).a()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension_lite).c()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension_lite ).d()); + EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a()); + EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb()); + EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension_lite ).has_c()); + EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d()); + EXPECT_FALSE(message.GetExtension(unittest::optional_public_import_message_extension_lite).has_e()); + EXPECT_FALSE(message.GetExtension(unittest::optional_lazy_message_extension_lite ).has_bb()); + + EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension_lite ).a()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension_lite ).c()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension_lite ).d()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_public_import_message_extension_lite).e()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_lazy_message_extension_lite ).bb()); // Enums without defaults are set to the first value in the enum. EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::optional_nested_enum_extension_lite )); @@ -1183,6 +1257,7 @@ void TestUtilLite::ExpectExtensionsClear( EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension_lite )); EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite)); EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite )); EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite )); EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite )); EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension_lite )); @@ -1231,6 +1306,11 @@ void TestUtilLite::ExpectExtensionsClear( EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::default_foreign_enum_extension_lite)); EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::default_import_enum_extension_lite )); + + EXPECT_FALSE(message.HasExtension(unittest::oneof_uint32_extension_lite)); + EXPECT_FALSE(message.GetExtension(unittest::oneof_nested_message_extension_lite).has_bb()); + EXPECT_FALSE(message.HasExtension(unittest::oneof_string_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::oneof_bytes_extension_lite)); } // ------------------------------------------------------------------- @@ -1260,6 +1340,7 @@ void TestUtilLite::ExpectRepeatedExtensionsModified( ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite)); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite )); ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite )); @@ -1285,6 +1366,7 @@ void TestUtilLite::ExpectRepeatedExtensionsModified( EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb()); EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c()); EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d()); + EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 0).bb()); EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0)); EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0)); @@ -1312,6 +1394,7 @@ void TestUtilLite::ExpectRepeatedExtensionsModified( EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb()); EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c()); EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d()); + EXPECT_EQ(527, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 1).bb()); EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1)); EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1)); diff --git a/src/google/protobuf/testdata/bad_utf8_string b/src/google/protobuf/testdata/bad_utf8_string new file mode 100644 index 0000000..a1337ec --- /dev/null +++ b/src/google/protobuf/testdata/bad_utf8_string @@ -0,0 +1 @@ +r \ No newline at end of file diff --git a/src/google/protobuf/testdata/golden_message b/src/google/protobuf/testdata/golden_message index 94898e4..0b7e655 100644 Binary files a/src/google/protobuf/testdata/golden_message and b/src/google/protobuf/testdata/golden_message differ diff --git a/src/google/protobuf/testdata/golden_message_oneof_implemented b/src/google/protobuf/testdata/golden_message_oneof_implemented new file mode 100644 index 0000000..b48c898 Binary files /dev/null and b/src/google/protobuf/testdata/golden_message_oneof_implemented differ diff --git a/src/google/protobuf/testdata/text_format_unittest_data.txt b/src/google/protobuf/testdata/text_format_unittest_data.txt index feea8f7..7a874b5 100644 --- a/src/google/protobuf/testdata/text_format_unittest_data.txt +++ b/src/google/protobuf/testdata/text_format_unittest_data.txt @@ -30,6 +30,12 @@ optional_foreign_enum: FOREIGN_BAZ optional_import_enum: IMPORT_BAZ optional_string_piece: "124" optional_cord: "125" +optional_public_import_message { + e: 126 +} +optional_lazy_message { + bb: 127 +} repeated_int32: 201 repeated_int32: 301 repeated_int64: 202 @@ -94,6 +100,12 @@ repeated_string_piece: "224" repeated_string_piece: "324" repeated_cord: "225" repeated_cord: "325" +repeated_lazy_message { + bb: 227 +} +repeated_lazy_message { + bb: 327 +} default_int32: 401 default_int64: 402 default_uint32: 403 @@ -114,3 +126,9 @@ default_foreign_enum: FOREIGN_FOO default_import_enum: IMPORT_FOO default_string_piece: "424" default_cord: "425" +oneof_uint32: 601 +oneof_nested_message { + bb: 602 +} +oneof_string: "603" +oneof_bytes: "604" diff --git a/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt b/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt new file mode 100644 index 0000000..ec95e1e --- /dev/null +++ b/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt @@ -0,0 +1,129 @@ +optional_int32: 101 +optional_int64: 102 +optional_uint32: 103 +optional_uint64: 104 +optional_sint32: 105 +optional_sint64: 106 +optional_fixed32: 107 +optional_fixed64: 108 +optional_sfixed32: 109 +optional_sfixed64: 110 +optional_float: 111 +optional_double: 112 +optional_bool: true +optional_string: "115" +optional_bytes: "116" +OptionalGroup { + a: 117 +} +optional_nested_message { + bb: 118 +} +optional_foreign_message { + c: 119 +} +optional_import_message { + d: 120 +} +optional_nested_enum: BAZ +optional_foreign_enum: FOREIGN_BAZ +optional_import_enum: IMPORT_BAZ +optional_string_piece: "124" +optional_cord: "125" +optional_public_import_message { + e: 126 +} +optional_lazy_message { + bb: 127 +} +repeated_int32: 201 +repeated_int32: 301 +repeated_int64: 202 +repeated_int64: 302 +repeated_uint32: 203 +repeated_uint32: 303 +repeated_uint64: 204 +repeated_uint64: 304 +repeated_sint32: 205 +repeated_sint32: 305 +repeated_sint64: 206 +repeated_sint64: 306 +repeated_fixed32: 207 +repeated_fixed32: 307 +repeated_fixed64: 208 +repeated_fixed64: 308 +repeated_sfixed32: 209 +repeated_sfixed32: 309 +repeated_sfixed64: 210 +repeated_sfixed64: 310 +repeated_float: 211 +repeated_float: 311 +repeated_double: 212 +repeated_double: 312 +repeated_bool: true +repeated_bool: false +repeated_string: "215" +repeated_string: "315" +repeated_bytes: "216" +repeated_bytes: "316" +RepeatedGroup { + a: 217 +} +RepeatedGroup { + a: 317 +} +repeated_nested_message { + bb: 218 +} +repeated_nested_message { + bb: 318 +} +repeated_foreign_message { + c: 219 +} +repeated_foreign_message { + c: 319 +} +repeated_import_message { + d: 220 +} +repeated_import_message { + d: 320 +} +repeated_nested_enum: BAR +repeated_nested_enum: BAZ +repeated_foreign_enum: FOREIGN_BAR +repeated_foreign_enum: FOREIGN_BAZ +repeated_import_enum: IMPORT_BAR +repeated_import_enum: IMPORT_BAZ +repeated_string_piece: "224" +repeated_string_piece: "324" +repeated_cord: "225" +repeated_cord: "325" +repeated_lazy_message { + bb: 227 +} +repeated_lazy_message { + bb: 327 +} +default_int32: 401 +default_int64: 402 +default_uint32: 403 +default_uint64: 404 +default_sint32: 405 +default_sint64: 406 +default_fixed32: 407 +default_fixed64: 408 +default_sfixed32: 409 +default_sfixed64: 410 +default_float: 411 +default_double: 412 +default_bool: false +default_string: "415" +default_bytes: "416" +default_nested_enum: FOO +default_foreign_enum: FOREIGN_FOO +default_import_enum: IMPORT_FOO +default_string_piece: "424" +default_cord: "425" +oneof_bytes: "604" diff --git a/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt b/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt new file mode 100644 index 0000000..e1011eb --- /dev/null +++ b/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt @@ -0,0 +1,134 @@ +optional_int32: 101 +optional_int64: 102 +optional_uint32: 103 +optional_uint64: 104 +optional_sint32: 105 +optional_sint64: 106 +optional_fixed32: 107 +optional_fixed64: 108 +optional_sfixed32: 109 +optional_sfixed64: 110 +optional_float: 111 +optional_double: 112 +optional_bool: true +optional_string: "115" +optional_bytes: "116" +OptionalGroup < + a: 117 +> +optional_nested_message < + bb: 118 +> +optional_foreign_message < + c: 119 +> +optional_import_message < + d: 120 +> +optional_nested_enum: BAZ +optional_foreign_enum: FOREIGN_BAZ +optional_import_enum: IMPORT_BAZ +optional_string_piece: "124" +optional_cord: "125" +optional_public_import_message < + e: 126 +> +optional_lazy_message < + bb: 127 +> +repeated_int32: 201 +repeated_int32: 301 +repeated_int64: 202 +repeated_int64: 302 +repeated_uint32: 203 +repeated_uint32: 303 +repeated_uint64: 204 +repeated_uint64: 304 +repeated_sint32: 205 +repeated_sint32: 305 +repeated_sint64: 206 +repeated_sint64: 306 +repeated_fixed32: 207 +repeated_fixed32: 307 +repeated_fixed64: 208 +repeated_fixed64: 308 +repeated_sfixed32: 209 +repeated_sfixed32: 309 +repeated_sfixed64: 210 +repeated_sfixed64: 310 +repeated_float: 211 +repeated_float: 311 +repeated_double: 212 +repeated_double: 312 +repeated_bool: true +repeated_bool: false +repeated_string: "215" +repeated_string: "315" +repeated_bytes: "216" +repeated_bytes: "316" +RepeatedGroup < + a: 217 +> +RepeatedGroup < + a: 317 +> +repeated_nested_message < + bb: 218 +> +repeated_nested_message < + bb: 318 +> +repeated_foreign_message < + c: 219 +> +repeated_foreign_message < + c: 319 +> +repeated_import_message < + d: 220 +> +repeated_import_message < + d: 320 +> +repeated_nested_enum: BAR +repeated_nested_enum: BAZ +repeated_foreign_enum: FOREIGN_BAR +repeated_foreign_enum: FOREIGN_BAZ +repeated_import_enum: IMPORT_BAR +repeated_import_enum: IMPORT_BAZ +repeated_string_piece: "224" +repeated_string_piece: "324" +repeated_cord: "225" +repeated_cord: "325" +repeated_lazy_message < + bb: 227 +> +repeated_lazy_message < + bb: 327 +> +default_int32: 401 +default_int64: 402 +default_uint32: 403 +default_uint64: 404 +default_sint32: 405 +default_sint64: 406 +default_fixed32: 407 +default_fixed64: 408 +default_sfixed32: 409 +default_sfixed64: 410 +default_float: 411 +default_double: 412 +default_bool: false +default_string: "415" +default_bytes: "416" +default_nested_enum: FOO +default_foreign_enum: FOREIGN_FOO +default_import_enum: IMPORT_FOO +default_string_piece: "424" +default_cord: "425" +oneof_uint32: 601 +oneof_nested_message < + bb: 602 +> +oneof_string: "603" +oneof_bytes: "604" diff --git a/src/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt b/src/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt new file mode 100644 index 0000000..95109f6 --- /dev/null +++ b/src/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt @@ -0,0 +1,129 @@ +optional_int32: 101 +optional_int64: 102 +optional_uint32: 103 +optional_uint64: 104 +optional_sint32: 105 +optional_sint64: 106 +optional_fixed32: 107 +optional_fixed64: 108 +optional_sfixed32: 109 +optional_sfixed64: 110 +optional_float: 111 +optional_double: 112 +optional_bool: true +optional_string: "115" +optional_bytes: "116" +OptionalGroup < + a: 117 +> +optional_nested_message < + bb: 118 +> +optional_foreign_message < + c: 119 +> +optional_import_message < + d: 120 +> +optional_nested_enum: BAZ +optional_foreign_enum: FOREIGN_BAZ +optional_import_enum: IMPORT_BAZ +optional_string_piece: "124" +optional_cord: "125" +optional_public_import_message < + e: 126 +> +optional_lazy_message < + bb: 127 +> +repeated_int32: 201 +repeated_int32: 301 +repeated_int64: 202 +repeated_int64: 302 +repeated_uint32: 203 +repeated_uint32: 303 +repeated_uint64: 204 +repeated_uint64: 304 +repeated_sint32: 205 +repeated_sint32: 305 +repeated_sint64: 206 +repeated_sint64: 306 +repeated_fixed32: 207 +repeated_fixed32: 307 +repeated_fixed64: 208 +repeated_fixed64: 308 +repeated_sfixed32: 209 +repeated_sfixed32: 309 +repeated_sfixed64: 210 +repeated_sfixed64: 310 +repeated_float: 211 +repeated_float: 311 +repeated_double: 212 +repeated_double: 312 +repeated_bool: true +repeated_bool: false +repeated_string: "215" +repeated_string: "315" +repeated_bytes: "216" +repeated_bytes: "316" +RepeatedGroup < + a: 217 +> +RepeatedGroup < + a: 317 +> +repeated_nested_message < + bb: 218 +> +repeated_nested_message < + bb: 318 +> +repeated_foreign_message < + c: 219 +> +repeated_foreign_message < + c: 319 +> +repeated_import_message < + d: 220 +> +repeated_import_message < + d: 320 +> +repeated_nested_enum: BAR +repeated_nested_enum: BAZ +repeated_foreign_enum: FOREIGN_BAR +repeated_foreign_enum: FOREIGN_BAZ +repeated_import_enum: IMPORT_BAR +repeated_import_enum: IMPORT_BAZ +repeated_string_piece: "224" +repeated_string_piece: "324" +repeated_cord: "225" +repeated_cord: "325" +repeated_lazy_message < + bb: 227 +> +repeated_lazy_message < + bb: 327 +> +default_int32: 401 +default_int64: 402 +default_uint32: 403 +default_uint64: 404 +default_sint32: 405 +default_sint64: 406 +default_fixed32: 407 +default_fixed64: 408 +default_sfixed32: 409 +default_sfixed64: 410 +default_float: 411 +default_double: 412 +default_bool: false +default_string: "415" +default_bytes: "416" +default_nested_enum: FOO +default_foreign_enum: FOREIGN_FOO +default_import_enum: IMPORT_FOO +default_string_piece: "424" +default_cord: "425" +oneof_bytes: "604" diff --git a/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt b/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt index 057beae..8c8b1eb 100644 --- a/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt +++ b/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt @@ -30,6 +30,12 @@ [protobuf_unittest.optional_import_enum_extension]: IMPORT_BAZ [protobuf_unittest.optional_string_piece_extension]: "124" [protobuf_unittest.optional_cord_extension]: "125" +[protobuf_unittest.optional_public_import_message_extension] { + e: 126 +} +[protobuf_unittest.optional_lazy_message_extension] { + bb: 127 +} [protobuf_unittest.repeated_int32_extension]: 201 [protobuf_unittest.repeated_int32_extension]: 301 [protobuf_unittest.repeated_int64_extension]: 202 @@ -94,6 +100,12 @@ [protobuf_unittest.repeated_string_piece_extension]: "324" [protobuf_unittest.repeated_cord_extension]: "225" [protobuf_unittest.repeated_cord_extension]: "325" +[protobuf_unittest.repeated_lazy_message_extension] { + bb: 227 +} +[protobuf_unittest.repeated_lazy_message_extension] { + bb: 327 +} [protobuf_unittest.default_int32_extension]: 401 [protobuf_unittest.default_int64_extension]: 402 [protobuf_unittest.default_uint32_extension]: 403 @@ -114,3 +126,9 @@ [protobuf_unittest.default_import_enum_extension]: IMPORT_FOO [protobuf_unittest.default_string_piece_extension]: "424" [protobuf_unittest.default_cord_extension]: "425" +[protobuf_unittest.oneof_uint32_extension]: 601 +[protobuf_unittest.oneof_nested_message_extension] { + bb: 602 +} +[protobuf_unittest.oneof_string_extension]: "603" +[protobuf_unittest.oneof_bytes_extension]: "604" diff --git a/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt b/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt new file mode 100644 index 0000000..132f744 --- /dev/null +++ b/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt @@ -0,0 +1,134 @@ +[protobuf_unittest.optional_int32_extension]: 101 +[protobuf_unittest.optional_int64_extension]: 102 +[protobuf_unittest.optional_uint32_extension]: 103 +[protobuf_unittest.optional_uint64_extension]: 104 +[protobuf_unittest.optional_sint32_extension]: 105 +[protobuf_unittest.optional_sint64_extension]: 106 +[protobuf_unittest.optional_fixed32_extension]: 107 +[protobuf_unittest.optional_fixed64_extension]: 108 +[protobuf_unittest.optional_sfixed32_extension]: 109 +[protobuf_unittest.optional_sfixed64_extension]: 110 +[protobuf_unittest.optional_float_extension]: 111 +[protobuf_unittest.optional_double_extension]: 112 +[protobuf_unittest.optional_bool_extension]: true +[protobuf_unittest.optional_string_extension]: "115" +[protobuf_unittest.optional_bytes_extension]: "116" +[protobuf_unittest.optionalgroup_extension] < + a: 117 +> +[protobuf_unittest.optional_nested_message_extension] < + bb: 118 +> +[protobuf_unittest.optional_foreign_message_extension] < + c: 119 +> +[protobuf_unittest.optional_import_message_extension] < + d: 120 +> +[protobuf_unittest.optional_nested_enum_extension]: BAZ +[protobuf_unittest.optional_foreign_enum_extension]: FOREIGN_BAZ +[protobuf_unittest.optional_import_enum_extension]: IMPORT_BAZ +[protobuf_unittest.optional_string_piece_extension]: "124" +[protobuf_unittest.optional_cord_extension]: "125" +[protobuf_unittest.optional_public_import_message_extension] < + e: 126 +> +[protobuf_unittest.optional_lazy_message_extension] < + bb: 127 +> +[protobuf_unittest.repeated_int32_extension]: 201 +[protobuf_unittest.repeated_int32_extension]: 301 +[protobuf_unittest.repeated_int64_extension]: 202 +[protobuf_unittest.repeated_int64_extension]: 302 +[protobuf_unittest.repeated_uint32_extension]: 203 +[protobuf_unittest.repeated_uint32_extension]: 303 +[protobuf_unittest.repeated_uint64_extension]: 204 +[protobuf_unittest.repeated_uint64_extension]: 304 +[protobuf_unittest.repeated_sint32_extension]: 205 +[protobuf_unittest.repeated_sint32_extension]: 305 +[protobuf_unittest.repeated_sint64_extension]: 206 +[protobuf_unittest.repeated_sint64_extension]: 306 +[protobuf_unittest.repeated_fixed32_extension]: 207 +[protobuf_unittest.repeated_fixed32_extension]: 307 +[protobuf_unittest.repeated_fixed64_extension]: 208 +[protobuf_unittest.repeated_fixed64_extension]: 308 +[protobuf_unittest.repeated_sfixed32_extension]: 209 +[protobuf_unittest.repeated_sfixed32_extension]: 309 +[protobuf_unittest.repeated_sfixed64_extension]: 210 +[protobuf_unittest.repeated_sfixed64_extension]: 310 +[protobuf_unittest.repeated_float_extension]: 211 +[protobuf_unittest.repeated_float_extension]: 311 +[protobuf_unittest.repeated_double_extension]: 212 +[protobuf_unittest.repeated_double_extension]: 312 +[protobuf_unittest.repeated_bool_extension]: true +[protobuf_unittest.repeated_bool_extension]: false +[protobuf_unittest.repeated_string_extension]: "215" +[protobuf_unittest.repeated_string_extension]: "315" +[protobuf_unittest.repeated_bytes_extension]: "216" +[protobuf_unittest.repeated_bytes_extension]: "316" +[protobuf_unittest.repeatedgroup_extension] < + a: 217 +> +[protobuf_unittest.repeatedgroup_extension] < + a: 317 +> +[protobuf_unittest.repeated_nested_message_extension] < + bb: 218 +> +[protobuf_unittest.repeated_nested_message_extension] < + bb: 318 +> +[protobuf_unittest.repeated_foreign_message_extension] < + c: 219 +> +[protobuf_unittest.repeated_foreign_message_extension] < + c: 319 +> +[protobuf_unittest.repeated_import_message_extension] < + d: 220 +> +[protobuf_unittest.repeated_import_message_extension] < + d: 320 +> +[protobuf_unittest.repeated_nested_enum_extension]: BAR +[protobuf_unittest.repeated_nested_enum_extension]: BAZ +[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAR +[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAZ +[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAR +[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAZ +[protobuf_unittest.repeated_string_piece_extension]: "224" +[protobuf_unittest.repeated_string_piece_extension]: "324" +[protobuf_unittest.repeated_cord_extension]: "225" +[protobuf_unittest.repeated_cord_extension]: "325" +[protobuf_unittest.repeated_lazy_message_extension] < + bb: 227 +> +[protobuf_unittest.repeated_lazy_message_extension] < + bb: 327 +> +[protobuf_unittest.default_int32_extension]: 401 +[protobuf_unittest.default_int64_extension]: 402 +[protobuf_unittest.default_uint32_extension]: 403 +[protobuf_unittest.default_uint64_extension]: 404 +[protobuf_unittest.default_sint32_extension]: 405 +[protobuf_unittest.default_sint64_extension]: 406 +[protobuf_unittest.default_fixed32_extension]: 407 +[protobuf_unittest.default_fixed64_extension]: 408 +[protobuf_unittest.default_sfixed32_extension]: 409 +[protobuf_unittest.default_sfixed64_extension]: 410 +[protobuf_unittest.default_float_extension]: 411 +[protobuf_unittest.default_double_extension]: 412 +[protobuf_unittest.default_bool_extension]: false +[protobuf_unittest.default_string_extension]: "415" +[protobuf_unittest.default_bytes_extension]: "416" +[protobuf_unittest.default_nested_enum_extension]: FOO +[protobuf_unittest.default_foreign_enum_extension]: FOREIGN_FOO +[protobuf_unittest.default_import_enum_extension]: IMPORT_FOO +[protobuf_unittest.default_string_piece_extension]: "424" +[protobuf_unittest.default_cord_extension]: "425" +[protobuf_unittest.oneof_uint32_extension]: 601 +[protobuf_unittest.oneof_nested_message_extension] < + bb: 602 +> +[protobuf_unittest.oneof_string_extension]: "603" +[protobuf_unittest.oneof_bytes_extension]: "604" diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc index e224781..9a5b35e 100644 --- a/src/google/protobuf/testing/file.cc +++ b/src/google/protobuf/testing/file.cc @@ -82,6 +82,24 @@ void File::ReadFileToStringOrDie(const string& name, string* output) { GOOGLE_CHECK(ReadFileToString(name, output)) << "Could not read: " << name; } +bool File::WriteStringToFile(const string& contents, const string& name) { + FILE* file = fopen(name.c_str(), "wb"); + if (file == NULL) { + GOOGLE_LOG(ERROR) << "fopen(" << name << ", \"wb\"): " << strerror(errno); + return false; + } + + if (fwrite(contents.data(), 1, contents.size(), file) != contents.size()) { + GOOGLE_LOG(ERROR) << "fwrite(" << name << "): " << strerror(errno); + return false; + } + + if (fclose(file) != 0) { + return false; + } + return true; +} + void File::WriteStringToFileOrDie(const string& contents, const string& name) { FILE* file = fopen(name.c_str(), "wb"); GOOGLE_CHECK(file != NULL) diff --git a/src/google/protobuf/testing/file.h b/src/google/protobuf/testing/file.h index a6b1c76..91ecce9 100644 --- a/src/google/protobuf/testing/file.h +++ b/src/google/protobuf/testing/file.h @@ -56,6 +56,10 @@ class File { static void ReadFileToStringOrDie(const string& name, string* output); // Create a file and write a string to it. + static bool WriteStringToFile(const string& contents, + const string& name); + + // Same as above, but crash on failure. static void WriteStringToFileOrDie(const string& contents, const string& name); @@ -73,6 +77,16 @@ class File { static void DeleteRecursively(const string& name, void* dummy1, void* dummy2); + static bool GetContents( + const string& name, string* output, bool /*is_default*/) { + return ReadFileToString(name, output); + } + + static bool SetContents( + const string& name, const string& contents, bool /*is_default*/) { + return WriteStringToFile(contents, name); + } + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(File); }; diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc index cd094d0..a8da6b1 100644 --- a/src/google/protobuf/testing/googletest.cc +++ b/src/google/protobuf/testing/googletest.cc @@ -223,16 +223,17 @@ ScopedMemoryLog::~ScopedMemoryLog() { active_log_ = NULL; } -const vector& ScopedMemoryLog::GetMessages(LogLevel dummy) const { - GOOGLE_CHECK_EQ(dummy, ERROR); - return messages_; +const vector& ScopedMemoryLog::GetMessages(LogLevel level) { + GOOGLE_CHECK(level == ERROR || + level == WARNING); + return messages_[level]; } void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename, int line, const string& message) { GOOGLE_CHECK(active_log_ != NULL); - if (level == ERROR) { - active_log_->messages_.push_back(message); + if (level == ERROR || level == WARNING) { + active_log_->messages_[level].push_back(message); } } diff --git a/src/google/protobuf/testing/googletest.h b/src/google/protobuf/testing/googletest.h index 71444c9..003be10 100644 --- a/src/google/protobuf/testing/googletest.h +++ b/src/google/protobuf/testing/googletest.h @@ -34,9 +34,15 @@ #ifndef GOOGLE_PROTOBUF_GOOGLETEST_H__ #define GOOGLE_PROTOBUF_GOOGLETEST_H__ +#include #include #include +// Disable death tests if we use exceptions in CHECK(). +#if !PROTOBUF_USE_EXCEPTIONS && defined(GTEST_HAS_DEATH_TEST) +#define PROTOBUF_HAS_DEATH_TEST +#endif + namespace google { namespace protobuf { @@ -60,6 +66,7 @@ string GetCapturedTestStderr(); // ScopedMemoryLog refers to LOGLEVEL_ERROR as just ERROR. #undef ERROR // defend against promiscuous windows.h static const LogLevel ERROR = LOGLEVEL_ERROR; +static const LogLevel WARNING = LOGLEVEL_WARNING; // Receives copies of all LOG(ERROR) messages while in scope. Sample usage: // { @@ -74,14 +81,11 @@ class ScopedMemoryLog { ScopedMemoryLog(); virtual ~ScopedMemoryLog(); - // Fetches all messages logged. The internal version of this class - // would only fetch messages at the given security level, but the protobuf - // open source version ignores the argument since we always pass ERROR - // anyway. - const vector& GetMessages(LogLevel dummy) const; + // Fetches all messages with the given severity level. + const vector& GetMessages(LogLevel error); private: - vector messages_; + map > messages_; LogHandler* old_handler_; static void HandleLog(LogLevel level, const char* filename, int line, diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index 137cbce..3ecb110 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -32,15 +32,18 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -48,10 +51,26 @@ #include #include #include +#include +#include namespace google { namespace protobuf { +namespace { + +inline bool IsHexNumber(const string& str) { + return (str.length() >= 2 && str[0] == '0' && + (str[1] == 'x' || str[1] == 'X')); +} + +inline bool IsOctNumber(const string& str) { + return (str.length() >= 2 && str[0] == '0' && + (str[1] >= '0' && str[1] < '8')); +} + +} // namespace + string Message::DebugString() const { string debug_string; @@ -93,6 +112,73 @@ void Message::PrintDebugString() const { // =========================================================================== +// Implementation of the parse information tree class. +TextFormat::ParseInfoTree::ParseInfoTree() { } + +TextFormat::ParseInfoTree::~ParseInfoTree() { + // Remove any nested information trees, as they are owned by this tree. + for (NestedMap::iterator it = nested_.begin(); it != nested_.end(); ++it) { + STLDeleteElements(&(it->second)); + } +} + +void TextFormat::ParseInfoTree::RecordLocation( + const FieldDescriptor* field, + TextFormat::ParseLocation location) { + locations_[field].push_back(location); +} + +TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::CreateNested( + const FieldDescriptor* field) { + // Owned by us in the map. + TextFormat::ParseInfoTree* instance = new TextFormat::ParseInfoTree(); + vector* trees = &nested_[field]; + GOOGLE_CHECK(trees); + trees->push_back(instance); + return instance; +} + +void CheckFieldIndex(const FieldDescriptor* field, int index) { + if (field == NULL) { return; } + + if (field->is_repeated() && index == -1) { + GOOGLE_LOG(DFATAL) << "Index must be in range of repeated field values. " + << "Field: " << field->name(); + } else if (!field->is_repeated() && index != -1) { + GOOGLE_LOG(DFATAL) << "Index must be -1 for singular fields." + << "Field: " << field->name(); + } +} + +TextFormat::ParseLocation TextFormat::ParseInfoTree::GetLocation( + const FieldDescriptor* field, int index) const { + CheckFieldIndex(field, index); + if (index == -1) { index = 0; } + + const vector* locations = + FindOrNull(locations_, field); + if (locations == NULL || index >= locations->size()) { + return TextFormat::ParseLocation(); + } + + return (*locations)[index]; +} + +TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested( + const FieldDescriptor* field, int index) const { + CheckFieldIndex(field, index); + if (index == -1) { index = 0; } + + const vector* trees = FindOrNull(nested_, field); + if (trees == NULL || index >= trees->size()) { + return NULL; + } + + return (*trees)[index]; +} + + +// =========================================================================== // Internal class for parsing an ASCII representation of a Protocol Message. // This class makes use of the Protocol Message compiler's tokenizer found // in //google/protobuf/io/tokenizer.h. Note that class's Parse @@ -107,9 +193,10 @@ void Message::PrintDebugString() const { class TextFormat::Parser::ParserImpl { public: - // Determines if repeated values for a non-repeated field are - // permitted, e.g., the string "foo: 1 foo: 2" for a - // required/optional field named "foo". + // Determines if repeated values for non-repeated fields and + // oneofs are permitted, e.g., the string "foo: 1 foo: 2" for a + // required/optional field named "foo", or "baz: 1 qux: 2" + // where "baz" and "qux" are members of the same oneof. enum SingularOverwritePolicy { ALLOW_SINGULAR_OVERWRITES = 0, // the last value is retained FORBID_SINGULAR_OVERWRITES = 1, // an error is issued @@ -118,12 +205,25 @@ class TextFormat::Parser::ParserImpl { ParserImpl(const Descriptor* root_message_type, io::ZeroCopyInputStream* input_stream, io::ErrorCollector* error_collector, - SingularOverwritePolicy singular_overwrite_policy) + TextFormat::Finder* finder, + ParseInfoTree* parse_info_tree, + SingularOverwritePolicy singular_overwrite_policy, + bool allow_case_insensitive_field, + bool allow_unknown_field, + bool allow_unknown_enum, + bool allow_field_number, + bool allow_relaxed_whitespace) : error_collector_(error_collector), + finder_(finder), + parse_info_tree_(parse_info_tree), tokenizer_error_collector_(this), tokenizer_(input_stream, &tokenizer_error_collector_), root_message_type_(root_message_type), singular_overwrite_policy_(singular_overwrite_policy), + allow_case_insensitive_field_(allow_case_insensitive_field), + allow_unknown_field_(allow_unknown_field), + allow_unknown_enum_(allow_unknown_enum), + allow_field_number_(allow_field_number), had_errors_(false) { // For backwards-compatibility with proto1, we need to allow the 'f' suffix // for floats. @@ -132,6 +232,11 @@ class TextFormat::Parser::ParserImpl { // '#' starts a comment. tokenizer_.set_comment_style(io::Tokenizer::SH_COMMENT_STYLE); + if (allow_relaxed_whitespace) { + tokenizer_.set_require_space_after_number(false); + tokenizer_.set_allow_multiline_strings(true); + } + // Consume the starting token. tokenizer_.Next(); } @@ -143,7 +248,7 @@ class TextFormat::Parser::ParserImpl { // GOOGLE_LOG(ERROR)). bool Parse(Message* output) { // Consume fields until we cannot do so anymore. - while(true) { + while (true) { if (LookingAtType(io::Tokenizer::TYPE_END)) { return !had_errors_; } @@ -228,6 +333,7 @@ class TextFormat::Parser::ParserImpl { return true; } + // Consumes the current field (as returned by the tokenizer) on the // passed in message. bool ConsumeField(Message* message) { @@ -237,6 +343,8 @@ class TextFormat::Parser::ParserImpl { string field_name; const FieldDescriptor* field = NULL; + int start_line = tokenizer_.current().line; + int start_column = tokenizer_.current().column; if (TryConsume("[")) { // Extension. @@ -249,72 +357,200 @@ class TextFormat::Parser::ParserImpl { } DO(Consume("]")); - field = reflection->FindKnownExtensionByName(field_name); + field = (finder_ != NULL + ? finder_->FindExtension(message, field_name) + : reflection->FindKnownExtensionByName(field_name)); if (field == NULL) { - ReportError("Extension \"" + field_name + "\" is not defined or " - "is not an extension of \"" + - descriptor->full_name() + "\"."); - return false; + if (!allow_unknown_field_) { + ReportError("Extension \"" + field_name + "\" is not defined or " + "is not an extension of \"" + + descriptor->full_name() + "\"."); + return false; + } else { + ReportWarning("Extension \"" + field_name + "\" is not defined or " + "is not an extension of \"" + + descriptor->full_name() + "\"."); + } } } else { DO(ConsumeIdentifier(&field_name)); - field = descriptor->FindFieldByName(field_name); - // Group names are expected to be capitalized as they appear in the - // .proto file, which actually matches their type names, not their field - // names. - if (field == NULL) { - string lower_field_name = field_name; - LowerString(&lower_field_name); - field = descriptor->FindFieldByName(lower_field_name); - // If the case-insensitive match worked but the field is NOT a group, - if (field != NULL && field->type() != FieldDescriptor::TYPE_GROUP) { + int32 field_number; + if (allow_field_number_ && safe_strto32(field_name, &field_number)) { + if (descriptor->IsExtensionNumber(field_number)) { + field = reflection->FindKnownExtensionByNumber(field_number); + } else { + field = descriptor->FindFieldByNumber(field_number); + } + } else { + field = descriptor->FindFieldByName(field_name); + // Group names are expected to be capitalized as they appear in the + // .proto file, which actually matches their type names, not their + // field names. + if (field == NULL) { + string lower_field_name = field_name; + LowerString(&lower_field_name); + field = descriptor->FindFieldByName(lower_field_name); + // If the case-insensitive match worked but the field is NOT a group, + if (field != NULL && field->type() != FieldDescriptor::TYPE_GROUP) { + field = NULL; + } + } + // Again, special-case group names as described above. + if (field != NULL && field->type() == FieldDescriptor::TYPE_GROUP + && field->message_type()->name() != field_name) { field = NULL; } - } - // Again, special-case group names as described above. - if (field != NULL && field->type() == FieldDescriptor::TYPE_GROUP - && field->message_type()->name() != field_name) { - field = NULL; + + if (field == NULL && allow_case_insensitive_field_) { + string lower_field_name = field_name; + LowerString(&lower_field_name); + field = descriptor->FindFieldByLowercaseName(lower_field_name); + } } if (field == NULL) { - ReportError("Message type \"" + descriptor->full_name() + - "\" has no field named \"" + field_name + "\"."); - return false; + if (!allow_unknown_field_) { + ReportError("Message type \"" + descriptor->full_name() + + "\" has no field named \"" + field_name + "\"."); + return false; + } else { + ReportWarning("Message type \"" + descriptor->full_name() + + "\" has no field named \"" + field_name + "\"."); + } } } - // Fail if the field is not repeated and it has already been specified. - if ((singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) && - !field->is_repeated() && reflection->HasField(*message, field)) { - ReportError("Non-repeated field \"" + field_name + - "\" is specified multiple times."); - return false; + // Skips unknown field. + if (field == NULL) { + GOOGLE_CHECK(allow_unknown_field_); + // Try to guess the type of this field. + // If this field is not a message, there should be a ":" between the + // field name and the field value and also the field value should not + // start with "{" or "<" which indicates the begining of a message body. + // If there is no ":" or there is a "{" or "<" after ":", this field has + // to be a message or the input is ill-formed. + if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) { + return SkipFieldValue(); + } else { + return SkipFieldMessage(); + } + } + + if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) { + // Fail if the field is not repeated and it has already been specified. + if (!field->is_repeated() && reflection->HasField(*message, field)) { + ReportError("Non-repeated field \"" + field_name + + "\" is specified multiple times."); + return false; + } + // Fail if the field is a member of a oneof and another member has already + // been specified. + const OneofDescriptor* oneof = field->containing_oneof(); + if (oneof != NULL && reflection->HasOneof(*message, oneof)) { + const FieldDescriptor* other_field = + reflection->GetOneofFieldDescriptor(*message, oneof); + ReportError("Field \"" + field_name + "\" is specified along with " + "field \"" + other_field->name() + "\", another member " + "of oneof \"" + oneof->name() + "\"."); + return false; + } } // Perform special handling for embedded message types. if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { // ':' is optional here. TryConsume(":"); - DO(ConsumeFieldMessage(message, reflection, field)); } else { + // ':' is required here. DO(Consume(":")); + } + + if (field->is_repeated() && TryConsume("[")) { + // Short repeated format, e.g. "foo: [1, 2, 3]" + while (true) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // Perform special handling for embedded message types. + DO(ConsumeFieldMessage(message, reflection, field)); + } else { + DO(ConsumeFieldValue(message, reflection, field)); + } + if (TryConsume("]")) { + break; + } + DO(Consume(",")); + } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + DO(ConsumeFieldMessage(message, reflection, field)); + } else { DO(ConsumeFieldValue(message, reflection, field)); } + // For historical reasons, fields may optionally be separated by commas or + // semicolons. + TryConsume(";") || TryConsume(","); + if (field->options().deprecated()) { ReportWarning("text format contains deprecated field \"" + field_name + "\""); } + // If a parse info tree exists, add the location for the parsed + // field. + if (parse_info_tree_ != NULL) { + RecordLocation(parse_info_tree_, field, + ParseLocation(start_line, start_column)); + } + + return true; + } + + // Skips the next field including the field's name and value. + bool SkipField() { + string field_name; + if (TryConsume("[")) { + // Extension name. + DO(ConsumeIdentifier(&field_name)); + while (TryConsume(".")) { + string part; + DO(ConsumeIdentifier(&part)); + field_name += "."; + field_name += part; + } + DO(Consume("]")); + } else { + DO(ConsumeIdentifier(&field_name)); + } + + // Try to guess the type of this field. + // If this field is not a message, there should be a ":" between the + // field name and the field value and also the field value should not + // start with "{" or "<" which indicates the begining of a message body. + // If there is no ":" or there is a "{" or "<" after ":", this field has + // to be a message or the input is ill-formed. + if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) { + DO(SkipFieldValue()); + } else { + DO(SkipFieldMessage()); + } + // For historical reasons, fields may optionally be separated by commas or + // semicolons. + TryConsume(";") || TryConsume(","); return true; } bool ConsumeFieldMessage(Message* message, const Reflection* reflection, const FieldDescriptor* field) { + + // If the parse information tree is not NULL, create a nested one + // for the nested message. + ParseInfoTree* parent = parse_info_tree_; + if (parent != NULL) { + parse_info_tree_ = CreateNested(parent, field); + } + string delimeter; if (TryConsume("<")) { delimeter = ">"; @@ -329,6 +565,26 @@ class TextFormat::Parser::ParserImpl { DO(ConsumeMessage(reflection->MutableMessage(message, field), delimeter)); } + + // Reset the parse information tree. + parse_info_tree_ = parent; + return true; + } + + // Skips the whole body of a message including the begining delimeter and + // the ending delimeter. + bool SkipFieldMessage() { + string delimeter; + if (TryConsume("<")) { + delimeter = ">"; + } else { + DO(Consume("{")); + delimeter = "}"; + } + while (!LookingAt(">") && !LookingAt("}")) { + DO(SkipField()); + } + DO(Consume(delimeter)); return true; } @@ -397,34 +653,57 @@ class TextFormat::Parser::ParserImpl { } case FieldDescriptor::CPPTYPE_BOOL: { - string value; - DO(ConsumeIdentifier(&value)); - - if (value == "true") { - SET_FIELD(Bool, true); - } else if (value == "false") { - SET_FIELD(Bool, false); + if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + uint64 value; + DO(ConsumeUnsignedInteger(&value, 1)); + SET_FIELD(Bool, value); } else { - ReportError("Invalid value for boolean field \"" + field->name() - + "\". Value: \"" + value + "\"."); - return false; + string value; + DO(ConsumeIdentifier(&value)); + if (value == "true" || value == "True" || value == "t") { + SET_FIELD(Bool, true); + } else if (value == "false" || value == "False" || value == "f") { + SET_FIELD(Bool, false); + } else { + ReportError("Invalid value for boolean field \"" + field->name() + + "\". Value: \"" + value + "\"."); + return false; + } } break; } case FieldDescriptor::CPPTYPE_ENUM: { string value; - DO(ConsumeIdentifier(&value)); - - // Find the enumeration value. const EnumDescriptor* enum_type = field->enum_type(); - const EnumValueDescriptor* enum_value - = enum_type->FindValueByName(value); + const EnumValueDescriptor* enum_value = NULL; + + if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + DO(ConsumeIdentifier(&value)); + // Find the enumeration value. + enum_value = enum_type->FindValueByName(value); + + } else if (LookingAt("-") || + LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + int64 int_value; + DO(ConsumeSignedInteger(&int_value, kint32max)); + value = SimpleItoa(int_value); // for error reporting + enum_value = enum_type->FindValueByNumber(int_value); + } else { + ReportError("Expected integer or identifier."); + return false; + } if (enum_value == NULL) { - ReportError("Unknown enumeration value of \"" + value + "\" for " - "field \"" + field->name() + "\"."); - return false; + if (!allow_unknown_enum_) { + ReportError("Unknown enumeration value of \"" + value + "\" for " + "field \"" + field->name() + "\"."); + return false; + } else { + ReportWarning("Unknown enumeration value of \"" + value + "\" for " + "field \"" + field->name() + "\"."); + return true; + } } SET_FIELD(Enum, enum_value); @@ -442,6 +721,60 @@ class TextFormat::Parser::ParserImpl { return true; } + bool SkipFieldValue() { + if (LookingAtType(io::Tokenizer::TYPE_STRING)) { + while (LookingAtType(io::Tokenizer::TYPE_STRING)) { + tokenizer_.Next(); + } + return true; + } + // Possible field values other than string: + // 12345 => TYPE_INTEGER + // -12345 => TYPE_SYMBOL + TYPE_INTEGER + // 1.2345 => TYPE_FLOAT + // -1.2345 => TYPE_SYMBOL + TYPE_FLOAT + // inf => TYPE_IDENTIFIER + // -inf => TYPE_SYMBOL + TYPE_IDENTIFIER + // TYPE_INTEGER => TYPE_IDENTIFIER + // Divides them into two group, one with TYPE_SYMBOL + // and the other without: + // Group one: + // 12345 => TYPE_INTEGER + // 1.2345 => TYPE_FLOAT + // inf => TYPE_IDENTIFIER + // TYPE_INTEGER => TYPE_IDENTIFIER + // Group two: + // -12345 => TYPE_SYMBOL + TYPE_INTEGER + // -1.2345 => TYPE_SYMBOL + TYPE_FLOAT + // -inf => TYPE_SYMBOL + TYPE_IDENTIFIER + // As we can see, the field value consists of an optional '-' and one of + // TYPE_INTEGER, TYPE_FLOAT and TYPE_IDENTIFIER. + bool has_minus = TryConsume("-"); + if (!LookingAtType(io::Tokenizer::TYPE_INTEGER) && + !LookingAtType(io::Tokenizer::TYPE_FLOAT) && + !LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + return false; + } + // Combination of '-' and TYPE_IDENTIFIER may result in an invalid field + // value while other combinations all generate valid values. + // We check if the value of this combination is valid here. + // TYPE_IDENTIFIER after a '-' should be one of the float values listed + // below: + // inf, inff, infinity, nan + if (has_minus && LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + string text = tokenizer_.current().text; + LowerString(&text); + if (text != "inf" && + text != "infinity" && + text != "nan") { + ReportError("Invalid float number: " + text); + return false; + } + } + tokenizer_.Next(); + return true; + } + // Returns true if the current token's text is equal to that specified. bool LookingAt(const string& text) { return tokenizer_.current().text == text; @@ -455,15 +788,23 @@ class TextFormat::Parser::ParserImpl { // Consumes an identifier and saves its value in the identifier parameter. // Returns false if the token is not of type IDENTFIER. bool ConsumeIdentifier(string* identifier) { - if (!LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { - ReportError("Expected identifier."); - return false; + if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + *identifier = tokenizer_.current().text; + tokenizer_.Next(); + return true; } - *identifier = tokenizer_.current().text; + // If allow_field_numer_ or allow_unknown_field_ is true, we should able + // to parse integer identifiers. + if ((allow_field_number_ || allow_unknown_field_) + && LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + *identifier = tokenizer_.current().text; + tokenizer_.Next(); + return true; + } - tokenizer_.Next(); - return true; + ReportError("Expected identifier."); + return false; } // Consumes a string and saves its value in the text parameter. @@ -530,6 +871,29 @@ class TextFormat::Parser::ParserImpl { return true; } + // Consumes a uint64 and saves its value in the value parameter. + // Accepts decimal numbers only, rejects hex or oct numbers. + bool ConsumeUnsignedDecimalInteger(uint64* value, uint64 max_value) { + if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + ReportError("Expected integer."); + return false; + } + + const string& text = tokenizer_.current().text; + if (IsHexNumber(text) || IsOctNumber(text)) { + ReportError("Expect a decimal number."); + return false; + } + + if (!io::Tokenizer::ParseInteger(text, max_value, value)) { + ReportError("Integer out of range."); + return false; + } + + tokenizer_.Next(); + return true; + } + // Consumes a double and saves its value in the value parameter. // Note that since the tokenizer does not support negative numbers, // we actually may consume an additional token (for the minus sign) in this @@ -547,7 +911,7 @@ class TextFormat::Parser::ParserImpl { if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { // We have found an integer value for the double. uint64 integer_value; - DO(ConsumeUnsignedInteger(&integer_value, kuint64max)); + DO(ConsumeUnsignedDecimalInteger(&integer_value, kuint64max)); *value = static_cast(integer_value); } else if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) { @@ -559,7 +923,8 @@ class TextFormat::Parser::ParserImpl { } else if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { string text = tokenizer_.current().text; LowerString(&text); - if (text == "inf" || text == "infinity") { + if (text == "inf" || + text == "infinity") { *value = std::numeric_limits::infinity(); tokenizer_.Next(); } else if (text == "nan") { @@ -616,7 +981,7 @@ class TextFormat::Parser::ParserImpl { explicit ParserErrorCollector(TextFormat::Parser::ParserImpl* parser) : parser_(parser) { } - virtual ~ParserErrorCollector() { }; + virtual ~ParserErrorCollector() { } virtual void AddError(int line, int column, const string& message) { parser_->ReportError(line, column, message); @@ -632,10 +997,16 @@ class TextFormat::Parser::ParserImpl { }; io::ErrorCollector* error_collector_; + TextFormat::Finder* finder_; + ParseInfoTree* parse_info_tree_; ParserErrorCollector tokenizer_error_collector_; io::Tokenizer tokenizer_; const Descriptor* root_message_type_; SingularOverwritePolicy singular_overwrite_policy_; + const bool allow_case_insensitive_field_; + const bool allow_unknown_field_; + const bool allow_unknown_enum_; + const bool allow_field_number_; bool had_errors_; }; @@ -661,7 +1032,7 @@ class TextFormat::Printer::TextGenerator { ~TextGenerator() { // Only BackUp() if we're sure we've successfully called Next() at least // once. - if (buffer_size_ > 0) { + if (!failed_ && buffer_size_ > 0) { output_->BackUp(buffer_size_); } } @@ -765,17 +1136,39 @@ class TextFormat::Printer::TextGenerator { // =========================================================================== +TextFormat::Finder::~Finder() { +} + TextFormat::Parser::Parser() : error_collector_(NULL), - allow_partial_(false) {} + finder_(NULL), + parse_info_tree_(NULL), + allow_partial_(false), + allow_case_insensitive_field_(false), + allow_unknown_field_(false), + allow_unknown_enum_(false), + allow_field_number_(false), + allow_relaxed_whitespace_(false), + allow_singular_overwrites_(false) { +} TextFormat::Parser::~Parser() {} bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, Message* output) { output->Clear(); + + ParserImpl::SingularOverwritePolicy overwrites_policy = + allow_singular_overwrites_ + ? ParserImpl::ALLOW_SINGULAR_OVERWRITES + : ParserImpl::FORBID_SINGULAR_OVERWRITES; + ParserImpl parser(output->GetDescriptor(), input, error_collector_, - ParserImpl::FORBID_SINGULAR_OVERWRITES); + finder_, parse_info_tree_, + overwrites_policy, + allow_case_insensitive_field_, allow_unknown_field_, + allow_unknown_enum_, allow_field_number_, + allow_relaxed_whitespace_); return MergeUsingImpl(input, output, &parser); } @@ -788,7 +1181,11 @@ bool TextFormat::Parser::ParseFromString(const string& input, bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, Message* output) { ParserImpl parser(output->GetDescriptor(), input, error_collector_, - ParserImpl::ALLOW_SINGULAR_OVERWRITES); + finder_, parse_info_tree_, + ParserImpl::ALLOW_SINGULAR_OVERWRITES, + allow_case_insensitive_field_, allow_unknown_field_, + allow_unknown_enum_, allow_field_number_, + allow_relaxed_whitespace_); return MergeUsingImpl(input, output, &parser); } @@ -798,7 +1195,7 @@ bool TextFormat::Parser::MergeFromString(const string& input, return Merge(&input_stream, output); } -bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input, +bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* /* input */, Message* output, ParserImpl* parser_impl) { if (!parser_impl->Parse(output)) return false; @@ -806,7 +1203,7 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input, vector missing_fields; output->FindInitializationErrors(&missing_fields); parser_impl->ReportError(-1, 0, "Message missing required fields: " + - JoinStrings(missing_fields, ", ")); + Join(missing_fields, ", ")); return false; } return true; @@ -818,7 +1215,11 @@ bool TextFormat::Parser::ParseFieldValueFromString( Message* output) { io::ArrayInputStream input_stream(input.data(), input.size()); ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_, - ParserImpl::ALLOW_SINGULAR_OVERWRITES); + finder_, parse_info_tree_, + ParserImpl::ALLOW_SINGULAR_OVERWRITES, + allow_case_insensitive_field_, allow_unknown_field_, + allow_unknown_enum_, allow_field_number_, + allow_relaxed_whitespace_); return parser.ParseField(field, output); } @@ -844,29 +1245,138 @@ bool TextFormat::Parser::ParseFieldValueFromString( // =========================================================================== +// The default implementation for FieldValuePrinter. The base class just +// does simple formatting. That way, deriving classes could decide to fallback +// to that behavior. +TextFormat::FieldValuePrinter::FieldValuePrinter() {} +TextFormat::FieldValuePrinter::~FieldValuePrinter() {} +string TextFormat::FieldValuePrinter::PrintBool(bool val) const { + return val ? "true" : "false"; +} +string TextFormat::FieldValuePrinter::PrintInt32(int32 val) const { + return SimpleItoa(val); +} +string TextFormat::FieldValuePrinter::PrintUInt32(uint32 val) const { + return SimpleItoa(val); +} +string TextFormat::FieldValuePrinter::PrintInt64(int64 val) const { + return SimpleItoa(val); +} +string TextFormat::FieldValuePrinter::PrintUInt64(uint64 val) const { + return SimpleItoa(val); +} +string TextFormat::FieldValuePrinter::PrintFloat(float val) const { + return SimpleFtoa(val); +} +string TextFormat::FieldValuePrinter::PrintDouble(double val) const { + return SimpleDtoa(val); +} +string TextFormat::FieldValuePrinter::PrintString(const string& val) const { + return StrCat("\"", CEscape(val), "\""); +} +string TextFormat::FieldValuePrinter::PrintBytes(const string& val) const { + return PrintString(val); +} +string TextFormat::FieldValuePrinter::PrintEnum(int32 val, + const string& name) const { + return name; +} +string TextFormat::FieldValuePrinter::PrintFieldName( + const Message& message, + const Reflection* reflection, + const FieldDescriptor* field) const { + if (field->is_extension()) { + // We special-case MessageSet elements for compatibility with proto1. + if (field->containing_type()->options().message_set_wire_format() + && field->type() == FieldDescriptor::TYPE_MESSAGE + && field->is_optional() + && field->extension_scope() == field->message_type()) { + return StrCat("[", field->message_type()->full_name(), "]"); + } else { + return StrCat("[", field->full_name(), "]"); + } + } else if (field->type() == FieldDescriptor::TYPE_GROUP) { + // Groups must be serialized with their original capitalization. + return field->message_type()->name(); + } else { + return field->name(); + } +} +string TextFormat::FieldValuePrinter::PrintMessageStart( + const Message& message, + int field_index, + int field_count, + bool single_line_mode) const { + return single_line_mode ? " { " : " {\n"; +} +string TextFormat::FieldValuePrinter::PrintMessageEnd( + const Message& message, + int field_index, + int field_count, + bool single_line_mode) const { + return single_line_mode ? "} " : "}\n"; +} + +namespace { +// Our own specialization: for UTF8 escaped strings. +class FieldValuePrinterUtf8Escaping : public TextFormat::FieldValuePrinter { + public: + virtual string PrintString(const string& val) const { + return StrCat("\"", strings::Utf8SafeCEscape(val), "\""); + } + virtual string PrintBytes(const string& val) const { + return TextFormat::FieldValuePrinter::PrintString(val); + } +}; + +} // namespace + TextFormat::Printer::Printer() : initial_indent_level_(0), single_line_mode_(false), + use_field_number_(false), use_short_repeated_primitives_(false), - utf8_string_escaping_(false) {} + hide_unknown_fields_(false), + print_message_fields_in_index_order_(false) { + SetUseUtf8StringEscaping(false); +} -TextFormat::Printer::~Printer() {} +TextFormat::Printer::~Printer() { + STLDeleteValues(&custom_printers_); +} + +void TextFormat::Printer::SetUseUtf8StringEscaping(bool as_utf8) { + SetDefaultFieldValuePrinter(as_utf8 + ? new FieldValuePrinterUtf8Escaping() + : new FieldValuePrinter()); +} + +void TextFormat::Printer::SetDefaultFieldValuePrinter( + const FieldValuePrinter* printer) { + default_field_value_printer_.reset(printer); +} + +bool TextFormat::Printer::RegisterFieldValuePrinter( + const FieldDescriptor* field, + const FieldValuePrinter* printer) { + return field != NULL + && printer != NULL + && custom_printers_.insert(make_pair(field, printer)).second; +} bool TextFormat::Printer::PrintToString(const Message& message, - string* output) { + string* output) const { GOOGLE_DCHECK(output) << "output specified is NULL"; output->clear(); io::StringOutputStream output_stream(output); - bool result = Print(message, &output_stream); - - return result; + return Print(message, &output_stream); } bool TextFormat::Printer::PrintUnknownFieldsToString( const UnknownFieldSet& unknown_fields, - string* output) { + string* output) const { GOOGLE_DCHECK(output) << "output specified is NULL"; output->clear(); @@ -875,7 +1385,7 @@ bool TextFormat::Printer::PrintUnknownFieldsToString( } bool TextFormat::Printer::Print(const Message& message, - io::ZeroCopyOutputStream* output) { + io::ZeroCopyOutputStream* output) const { TextGenerator generator(output, initial_indent_level_); Print(message, generator); @@ -886,7 +1396,7 @@ bool TextFormat::Printer::Print(const Message& message, bool TextFormat::Printer::PrintUnknownFields( const UnknownFieldSet& unknown_fields, - io::ZeroCopyOutputStream* output) { + io::ZeroCopyOutputStream* output) const { TextGenerator generator(output, initial_indent_level_); PrintUnknownFields(unknown_fields, generator); @@ -895,22 +1405,37 @@ bool TextFormat::Printer::PrintUnknownFields( return !generator.failed(); } +namespace { +// Comparison functor for sorting FieldDescriptors by field index. +struct FieldIndexSorter { + bool operator()(const FieldDescriptor* left, + const FieldDescriptor* right) const { + return left->index() < right->index(); + } +}; +} // namespace + void TextFormat::Printer::Print(const Message& message, - TextGenerator& generator) { + TextGenerator& generator) const { const Reflection* reflection = message.GetReflection(); vector fields; reflection->ListFields(message, &fields); + if (print_message_fields_in_index_order_) { + sort(fields.begin(), fields.end(), FieldIndexSorter()); + } for (int i = 0; i < fields.size(); i++) { PrintField(message, reflection, fields[i], generator); } - PrintUnknownFields(reflection->GetUnknownFields(message), generator); + if (!hide_unknown_fields_) { + PrintUnknownFields(reflection->GetUnknownFields(message), generator); + } } void TextFormat::Printer::PrintFieldValueToString( const Message& message, const FieldDescriptor* field, int index, - string* output) { + string* output) const { GOOGLE_DCHECK(output) << "output specified is NULL"; @@ -924,7 +1449,7 @@ void TextFormat::Printer::PrintFieldValueToString( void TextFormat::Printer::PrintField(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator) { + TextGenerator& generator) const { if (use_short_repeated_primitives_ && field->is_repeated() && field->cpp_type() != FieldDescriptor::CPPTYPE_STRING && @@ -942,35 +1467,30 @@ void TextFormat::Printer::PrintField(const Message& message, } for (int j = 0; j < count; ++j) { + const int field_index = field->is_repeated() ? j : -1; + PrintFieldName(message, reflection, field, generator); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - if (single_line_mode_) { - generator.Print(" { "); - } else { - generator.Print(" {\n"); - generator.Indent(); - } + const FieldValuePrinter* printer = FindWithDefault( + custom_printers_, field, default_field_value_printer_.get()); + const Message& sub_message = + field->is_repeated() + ? reflection->GetRepeatedMessage(message, field, j) + : reflection->GetMessage(message, field); + generator.Print( + printer->PrintMessageStart( + sub_message, field_index, count, single_line_mode_)); + generator.Indent(); + Print(sub_message, generator); + generator.Outdent(); + generator.Print( + printer->PrintMessageEnd( + sub_message, field_index, count, single_line_mode_)); } else { generator.Print(": "); - } - - // Write the field value. - int field_index = j; - if (!field->is_repeated()) { - field_index = -1; - } - - PrintFieldValue(message, reflection, field, field_index, generator); - - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - if (single_line_mode_) { - generator.Print("} "); - } else { - generator.Outdent(); - generator.Print("}\n"); - } - } else { + // Write the field value. + PrintFieldValue(message, reflection, field, field_index, generator); if (single_line_mode_) { generator.Print(" "); } else { @@ -980,10 +1500,11 @@ void TextFormat::Printer::PrintField(const Message& message, } } -void TextFormat::Printer::PrintShortRepeatedField(const Message& message, - const Reflection* reflection, - const FieldDescriptor* field, - TextGenerator& generator) { +void TextFormat::Printer::PrintShortRepeatedField( + const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + TextGenerator& generator) const { // Print primitive repeated field in short form. PrintFieldName(message, reflection, field, generator); @@ -1003,27 +1524,17 @@ void TextFormat::Printer::PrintShortRepeatedField(const Message& message, void TextFormat::Printer::PrintFieldName(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator) { - if (field->is_extension()) { - generator.Print("["); - // We special-case MessageSet elements for compatibility with proto1. - if (field->containing_type()->options().message_set_wire_format() - && field->type() == FieldDescriptor::TYPE_MESSAGE - && field->is_optional() - && field->extension_scope() == field->message_type()) { - generator.Print(field->message_type()->full_name()); - } else { - generator.Print(field->full_name()); - } - generator.Print("]"); - } else { - if (field->type() == FieldDescriptor::TYPE_GROUP) { - // Groups must be serialized with their original capitalization. - generator.Print(field->message_type()->name()); - } else { - generator.Print(field->name()); - } + TextGenerator& generator) const { + // if use_field_number_ is true, prints field number instead + // of field name. + if (use_field_number_) { + generator.Print(SimpleItoa(field->number())); + return; } + + const FieldValuePrinter* printer = FindWithDefault( + custom_printers_, field, default_field_value_printer_.get()); + generator.Print(printer->PrintFieldName(message, reflection, field)); } void TextFormat::Printer::PrintFieldValue( @@ -1031,66 +1542,60 @@ void TextFormat::Printer::PrintFieldValue( const Reflection* reflection, const FieldDescriptor* field, int index, - TextGenerator& generator) { + TextGenerator& generator) const { GOOGLE_DCHECK(field->is_repeated() || (index == -1)) << "Index must be -1 for non-repeated fields"; + const FieldValuePrinter* printer + = FindWithDefault(custom_printers_, field, + default_field_value_printer_.get()); + switch (field->cpp_type()) { -#define OUTPUT_FIELD(CPPTYPE, METHOD, TO_STRING) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - generator.Print(TO_STRING(field->is_repeated() ? \ - reflection->GetRepeated##METHOD(message, field, index) : \ - reflection->Get##METHOD(message, field))); \ - break; \ - - OUTPUT_FIELD( INT32, Int32, SimpleItoa); - OUTPUT_FIELD( INT64, Int64, SimpleItoa); - OUTPUT_FIELD(UINT32, UInt32, SimpleItoa); - OUTPUT_FIELD(UINT64, UInt64, SimpleItoa); - OUTPUT_FIELD( FLOAT, Float, SimpleFtoa); - OUTPUT_FIELD(DOUBLE, Double, SimpleDtoa); +#define OUTPUT_FIELD(CPPTYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + generator.Print(printer->Print##METHOD(field->is_repeated() \ + ? reflection->GetRepeated##METHOD(message, field, index) \ + : reflection->Get##METHOD(message, field))); \ + break + + OUTPUT_FIELD( INT32, Int32); + OUTPUT_FIELD( INT64, Int64); + OUTPUT_FIELD(UINT32, UInt32); + OUTPUT_FIELD(UINT64, UInt64); + OUTPUT_FIELD( FLOAT, Float); + OUTPUT_FIELD(DOUBLE, Double); + OUTPUT_FIELD( BOOL, Bool); #undef OUTPUT_FIELD - case FieldDescriptor::CPPTYPE_STRING: { - string scratch; - const string& value = field->is_repeated() ? - reflection->GetRepeatedStringReference( - message, field, index, &scratch) : - reflection->GetStringReference(message, field, &scratch); - - generator.Print("\""); - if (utf8_string_escaping_) { - generator.Print(strings::Utf8SafeCEscape(value)); - } else { - generator.Print(CEscape(value)); - } - generator.Print("\""); - - break; + case FieldDescriptor::CPPTYPE_STRING: { + string scratch; + const string& value = field->is_repeated() + ? reflection->GetRepeatedStringReference( + message, field, index, &scratch) + : reflection->GetStringReference(message, field, &scratch); + if (field->type() == FieldDescriptor::TYPE_STRING) { + generator.Print(printer->PrintString(value)); + } else { + GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_BYTES); + generator.Print(printer->PrintBytes(value)); } + break; + } - case FieldDescriptor::CPPTYPE_BOOL: - if (field->is_repeated()) { - generator.Print(reflection->GetRepeatedBool(message, field, index) - ? "true" : "false"); - } else { - generator.Print(reflection->GetBool(message, field) - ? "true" : "false"); - } - break; - - case FieldDescriptor::CPPTYPE_ENUM: - generator.Print(field->is_repeated() ? - reflection->GetRepeatedEnum(message, field, index)->name() : - reflection->GetEnum(message, field)->name()); - break; + case FieldDescriptor::CPPTYPE_ENUM: { + const EnumValueDescriptor *enum_val = field->is_repeated() + ? reflection->GetRepeatedEnum(message, field, index) + : reflection->GetEnum(message, field); + generator.Print(printer->PrintEnum(enum_val->number(), enum_val->name())); + break; + } - case FieldDescriptor::CPPTYPE_MESSAGE: - Print(field->is_repeated() ? - reflection->GetRepeatedMessage(message, field, index) : - reflection->GetMessage(message, field), - generator); - break; + case FieldDescriptor::CPPTYPE_MESSAGE: + Print(field->is_repeated() + ? reflection->GetRepeatedMessage(message, field, index) + : reflection->GetMessage(message, field), + generator); + break; } } @@ -1143,7 +1648,7 @@ static string PaddedHex(IntType value) { } void TextFormat::Printer::PrintUnknownFields( - const UnknownFieldSet& unknown_fields, TextGenerator& generator) { + const UnknownFieldSet& unknown_fields, TextGenerator& generator) const { for (int i = 0; i < unknown_fields.field_count(); i++) { const UnknownField& field = unknown_fields.field(i); string field_number = SimpleItoa(field.number()); diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index e78e104..b4cba1d 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -38,9 +38,14 @@ #ifndef GOOGLE_PROTOBUF_TEXT_FORMAT_H__ #define GOOGLE_PROTOBUF_TEXT_FORMAT_H__ +#include +#include #include -#include +#include + +#include #include +#include namespace google { namespace protobuf { @@ -82,6 +87,41 @@ class LIBPROTOBUF_EXPORT TextFormat { int index, string* output); + // The default printer that converts scalar values from fields into + // their string representation. + // You can derive from this FieldValuePrinter if you want to have + // fields to be printed in a different way and register it at the + // Printer. + class LIBPROTOBUF_EXPORT FieldValuePrinter { + public: + FieldValuePrinter(); + virtual ~FieldValuePrinter(); + virtual string PrintBool(bool val) const; + virtual string PrintInt32(int32 val) const; + virtual string PrintUInt32(uint32 val) const; + virtual string PrintInt64(int64 val) const; + virtual string PrintUInt64(uint64 val) const; + virtual string PrintFloat(float val) const; + virtual string PrintDouble(double val) const; + virtual string PrintString(const string& val) const; + virtual string PrintBytes(const string& val) const; + virtual string PrintEnum(int32 val, const string& name) const; + virtual string PrintFieldName(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field) const; + virtual string PrintMessageStart(const Message& message, + int field_index, + int field_count, + bool single_line_mode) const; + virtual string PrintMessageEnd(const Message& message, + int field_index, + int field_count, + bool single_line_mode) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldValuePrinter); + }; + // Class for those users which require more fine-grained control over how // a protobuffer message is printed out. class LIBPROTOBUF_EXPORT Printer { @@ -90,20 +130,20 @@ class LIBPROTOBUF_EXPORT TextFormat { ~Printer(); // Like TextFormat::Print - bool Print(const Message& message, io::ZeroCopyOutputStream* output); + bool Print(const Message& message, io::ZeroCopyOutputStream* output) const; // Like TextFormat::PrintUnknownFields bool PrintUnknownFields(const UnknownFieldSet& unknown_fields, - io::ZeroCopyOutputStream* output); + io::ZeroCopyOutputStream* output) const; // Like TextFormat::PrintToString - bool PrintToString(const Message& message, string* output); + bool PrintToString(const Message& message, string* output) const; // Like TextFormat::PrintUnknownFieldsToString bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields, - string* output); + string* output) const; // Like TextFormat::PrintFieldValueToString void PrintFieldValueToString(const Message& message, const FieldDescriptor* field, int index, - string* output); + string* output) const; // Adjust the initial indent level of all output. Each indent level is // equal to two spaces. @@ -117,12 +157,20 @@ class LIBPROTOBUF_EXPORT TextFormat { single_line_mode_ = single_line_mode; } + bool IsInSingleLineMode() { + return single_line_mode_; + } + + // If use_field_number is true, uses field number instead of field name. + void SetUseFieldNumber(bool use_field_number) { + use_field_number_ = use_field_number; + } + // Set true to print repeated primitives in a format like: // field_name: [1, 2, 3, 4] // instead of printing each value on its own line. Short format applies // only to primitive values -- i.e. everything except strings and - // sub-messages/groups. Note that at present this format is not recognized - // by the parser. + // sub-messages/groups. void SetUseShortRepeatedPrimitives(bool use_short_repeated_primitives) { use_short_repeated_primitives_ = use_short_repeated_primitives; } @@ -130,11 +178,41 @@ class LIBPROTOBUF_EXPORT TextFormat { // Set true to output UTF-8 instead of ASCII. The only difference // is that bytes >= 0x80 in string fields will not be escaped, // because they are assumed to be part of UTF-8 multi-byte - // sequences. - void SetUseUtf8StringEscaping(bool as_utf8) { - utf8_string_escaping_ = as_utf8; + // sequences. This will change the default FieldValuePrinter. + void SetUseUtf8StringEscaping(bool as_utf8); + + // Set the default FieldValuePrinter that is used for all fields that + // don't have a field-specific printer registered. + // Takes ownership of the printer. + void SetDefaultFieldValuePrinter(const FieldValuePrinter* printer); + + // Sets whether we want to hide unknown fields or not. + // Usually unknown fields are printed in a generic way that includes the + // tag number of the field instead of field name. However, sometimes it + // is useful to be able to print the message without unknown fields (e.g. + // for the python protobuf version to maintain consistency between its pure + // python and c++ implementations). + void SetHideUnknownFields(bool hide) { + hide_unknown_fields_ = hide; + } + + // If print_message_fields_in_index_order is true, print fields of a proto + // message using the order defined in source code instead of the field + // number. By default, use the field number order. + void SetPrintMessageFieldsInIndexOrder( + bool print_message_fields_in_index_order) { + print_message_fields_in_index_order_ = + print_message_fields_in_index_order; } + // Register a custom field-specific FieldValuePrinter for fields + // with a particular FieldDescriptor. + // Returns "true" if the registration succeeded, or "false", if there is + // already a printer for that FieldDescriptor. + // Takes ownership of the printer on successful registration. + bool RegisterFieldValuePrinter(const FieldDescriptor* field, + const FieldValuePrinter* printer); + private: // Forward declaration of an internal class used to print the text // output to the OutputStream (see text_format.cc for implementation). @@ -143,26 +221,26 @@ class LIBPROTOBUF_EXPORT TextFormat { // Internal Print method, used for writing to the OutputStream via // the TextGenerator class. void Print(const Message& message, - TextGenerator& generator); + TextGenerator& generator) const; // Print a single field. void PrintField(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator); + TextGenerator& generator) const; // Print a repeated primitive field in short form. void PrintShortRepeatedField(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator); + TextGenerator& generator) const; // Print the name of a field -- i.e. everything that comes before the // ':' for a single name/value pair. void PrintFieldName(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator); + TextGenerator& generator) const; // Outputs a textual representation of the value of the field supplied on // the message supplied or the default value if not set. @@ -170,21 +248,30 @@ class LIBPROTOBUF_EXPORT TextFormat { const Reflection* reflection, const FieldDescriptor* field, int index, - TextGenerator& generator); + TextGenerator& generator) const; // Print the fields in an UnknownFieldSet. They are printed by tag number // only. Embedded messages are heuristically identified by attempting to // parse them. void PrintUnknownFields(const UnknownFieldSet& unknown_fields, - TextGenerator& generator); + TextGenerator& generator) const; int initial_indent_level_; bool single_line_mode_; + bool use_field_number_; + bool use_short_repeated_primitives_; - bool utf8_string_escaping_; + bool hide_unknown_fields_; + + bool print_message_fields_in_index_order_; + + scoped_ptr default_field_value_printer_; + typedef map CustomPrinterMap; + CustomPrinterMap custom_printers_; }; // Parses a text-format protocol message from the given input stream to @@ -207,6 +294,71 @@ class LIBPROTOBUF_EXPORT TextFormat { const FieldDescriptor* field, Message* message); + // Interface that TextFormat::Parser can use to find extensions. + // This class may be extended in the future to find more information + // like fields, etc. + class LIBPROTOBUF_EXPORT Finder { + public: + virtual ~Finder(); + + // Try to find an extension of *message by fully-qualified field + // name. Returns NULL if no extension is known for this name or number. + virtual const FieldDescriptor* FindExtension( + Message* message, + const string& name) const = 0; + }; + + // A location in the parsed text. + struct ParseLocation { + int line; + int column; + + ParseLocation() : line(-1), column(-1) {} + ParseLocation(int line_param, int column_param) + : line(line_param), column(column_param) {} + }; + + // Data structure which is populated with the locations of each field + // value parsed from the text. + class LIBPROTOBUF_EXPORT ParseInfoTree { + public: + ParseInfoTree(); + ~ParseInfoTree(); + + // Returns the parse location for index-th value of the field in the parsed + // text. If none exists, returns a location with line = -1. Index should be + // -1 for not-repeated fields. + ParseLocation GetLocation(const FieldDescriptor* field, int index) const; + + // Returns the parse info tree for the given field, which must be a message + // type. The nested information tree is owned by the root tree and will be + // deleted when it is deleted. + ParseInfoTree* GetTreeForNested(const FieldDescriptor* field, + int index) const; + + private: + // Allow the text format parser to record information into the tree. + friend class TextFormat; + + // Records the starting location of a single value for a field. + void RecordLocation(const FieldDescriptor* field, ParseLocation location); + + // Create and records a nested tree for a nested message field. + ParseInfoTree* CreateNested(const FieldDescriptor* field); + + // Defines the map from the index-th field descriptor to its parse location. + typedef map > LocationMap; + + // Defines the map from the index-th field descriptor to the nested parse + // info tree. + typedef map > NestedMap; + + LocationMap locations_; + NestedMap nested_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParseInfoTree); + }; + // For more control over parsing, use this class. class LIBPROTOBUF_EXPORT Parser { public: @@ -228,17 +380,43 @@ class LIBPROTOBUF_EXPORT TextFormat { error_collector_ = error_collector; } + // Set how parser finds extensions. If NULL (the default), the + // parser will use the standard Reflection object associated with + // the message being parsed. + void SetFinder(Finder* finder) { + finder_ = finder; + } + + // Sets where location information about the parse will be written. If NULL + // (the default), then no location will be written. + void WriteLocationsTo(ParseInfoTree* tree) { + parse_info_tree_ = tree; + } + // Normally parsing fails if, after parsing, output->IsInitialized() // returns false. Call AllowPartialMessage(true) to skip this check. void AllowPartialMessage(bool allow) { allow_partial_ = allow; } + // Allow field names to be matched case-insensitively. + // This is not advisable if there are fields that only differ in case, or + // if you want to enforce writing in the canonical form. + // This is 'false' by default. + void AllowCaseInsensitiveField(bool allow) { + allow_case_insensitive_field_ = allow; + } + // Like TextFormat::ParseFieldValueFromString bool ParseFieldValueFromString(const string& input, const FieldDescriptor* field, Message* output); + + void AllowFieldNumber(bool allow) { + allow_field_number_ = allow; + } + private: // Forward declaration of an internal class used to parse text // representations (see text_format.cc for implementation). @@ -251,13 +429,44 @@ class LIBPROTOBUF_EXPORT TextFormat { ParserImpl* parser_impl); io::ErrorCollector* error_collector_; + Finder* finder_; + ParseInfoTree* parse_info_tree_; bool allow_partial_; + bool allow_case_insensitive_field_; + bool allow_unknown_field_; + bool allow_unknown_enum_; + bool allow_field_number_; + bool allow_relaxed_whitespace_; + bool allow_singular_overwrites_; }; + private: + // Hack: ParseInfoTree declares TextFormat as a friend which should extend + // the friendship to TextFormat::Parser::ParserImpl, but unfortunately some + // old compilers (e.g. GCC 3.4.6) don't implement this correctly. We provide + // helpers for ParserImpl to call methods of ParseInfoTree. + static inline void RecordLocation(ParseInfoTree* info_tree, + const FieldDescriptor* field, + ParseLocation location); + static inline ParseInfoTree* CreateNested(ParseInfoTree* info_tree, + const FieldDescriptor* field); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormat); }; +inline void TextFormat::RecordLocation(ParseInfoTree* info_tree, + const FieldDescriptor* field, + ParseLocation location) { + info_tree->RecordLocation(field, location); +} + + +inline TextFormat::ParseInfoTree* TextFormat::CreateNested( + ParseInfoTree* info_tree, const FieldDescriptor* field) { + return info_tree->CreateNested(field); +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index ddf8ff7..b3cf7b8 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -74,10 +74,11 @@ const string kEscapeTestStringEscaped = class TextFormatTest : public testing::Test { public: static void SetUpTestCase() { - File::ReadFileToStringOrDie( - TestSourceDir() - + "/google/protobuf/testdata/text_format_unittest_data.txt", - &static_proto_debug_string_); + GOOGLE_CHECK_OK(File::GetContents( + TestSourceDir() + + "/google/protobuf/" + "testdata/text_format_unittest_data_oneof_implemented.txt", + &static_proto_debug_string_, true)); } TextFormatTest() : proto_debug_string_(static_proto_debug_string_) {} @@ -95,11 +96,10 @@ string TextFormatTest::static_proto_debug_string_; class TextFormatExtensionsTest : public testing::Test { public: static void SetUpTestCase() { - File::ReadFileToStringOrDie( - TestSourceDir() - + "/google/protobuf/testdata/" - "text_format_unittest_extensions_data.txt", - &static_proto_debug_string_); + GOOGLE_CHECK_OK(File::GetContents(TestSourceDir() + + "/google/protobuf/testdata/" + "text_format_unittest_extensions_data.txt", + &static_proto_debug_string_, true)); } TextFormatExtensionsTest() @@ -205,16 +205,25 @@ TEST_F(TextFormatTest, StringEscape) { TEST_F(TextFormatTest, Utf8DebugString) { // Set the string value to test. proto_.set_optional_string("\350\260\267\346\255\214"); + proto_.set_optional_bytes("\350\260\267\346\255\214"); // Get the DebugString from the proto. string debug_string = proto_.DebugString(); string utf8_debug_string = proto_.Utf8DebugString(); // Hardcode a correct value to test against. - string correct_utf8_string = "optional_string: " + string correct_utf8_string = + "optional_string: " "\"\350\260\267\346\255\214\"" + "\n" + "optional_bytes: " + "\"\\350\\260\\267\\346\\255\\214\"" "\n"; - string correct_string = "optional_string: " + string correct_string = + "optional_string: " + "\"\\350\\260\\267\\346\\255\\214\"" + "\n" + "optional_bytes: " "\"\\350\\260\\267\\346\\255\\214\"" "\n"; @@ -253,6 +262,31 @@ TEST_F(TextFormatTest, PrintUnknownFields) { message.DebugString()); } +TEST_F(TextFormatTest, PrintUnknownFieldsHidden) { + // Test printing of unknown fields in a message when supressed. + + unittest::OneString message; + message.set_data("data"); + UnknownFieldSet* unknown_fields = message.mutable_unknown_fields(); + + unknown_fields->AddVarint(5, 1); + unknown_fields->AddFixed32(5, 2); + unknown_fields->AddFixed64(5, 3); + unknown_fields->AddLengthDelimited(5, "4"); + unknown_fields->AddGroup(5)->AddVarint(10, 5); + + unknown_fields->AddVarint(8, 1); + unknown_fields->AddVarint(8, 2); + unknown_fields->AddVarint(8, 3); + + TextFormat::Printer printer; + printer.SetHideUnknownFields(true); + string output; + printer.PrintToString(message, &output); + + EXPECT_EQ("data: \"data\"\n", output); +} + TEST_F(TextFormatTest, PrintUnknownMessage) { // Test heuristic printing of messages in an UnknownFieldSet. @@ -339,6 +373,161 @@ TEST_F(TextFormatTest, PrintMessageSingleLine) { text); } +TEST_F(TextFormatTest, PrintBufferTooSmall) { + // Test printing a message to a buffer that is too small. + + protobuf_unittest::TestAllTypes message; + + message.add_repeated_string("abc"); + message.add_repeated_string("def"); + + char buffer[1] = ""; + io::ArrayOutputStream output_stream(buffer, 1); + EXPECT_FALSE(TextFormat::Print(message, &output_stream)); + EXPECT_EQ(buffer[0], 'r'); + EXPECT_EQ(output_stream.ByteCount(), 1); +} + +// A printer that appends 'u' to all unsigned int32. +class CustomUInt32FieldValuePrinter : public TextFormat::FieldValuePrinter { + public: + virtual string PrintUInt32(uint32 val) const { + return StrCat(FieldValuePrinter::PrintUInt32(val), "u"); + } +}; + +TEST_F(TextFormatTest, DefaultCustomFieldPrinter) { + protobuf_unittest::TestAllTypes message; + + message.set_optional_uint32(42); + message.add_repeated_uint32(1); + message.add_repeated_uint32(2); + message.add_repeated_uint32(3); + + TextFormat::Printer printer; + printer.SetDefaultFieldValuePrinter(new CustomUInt32FieldValuePrinter()); + // Let's see if that works well together with the repeated primitives: + printer.SetUseShortRepeatedPrimitives(true); + string text; + printer.PrintToString(message, &text); + EXPECT_EQ("optional_uint32: 42u\nrepeated_uint32: [1u, 2u, 3u]\n", text); +} + +class CustomInt32FieldValuePrinter : public TextFormat::FieldValuePrinter { + public: + virtual string PrintInt32(int32 val) const { + return StrCat("value-is(", FieldValuePrinter::PrintInt32(val), ")"); + } +}; + +TEST_F(TextFormatTest, FieldSpecificCustomPrinter) { + protobuf_unittest::TestAllTypes message; + + message.set_optional_int32(42); // This will be handled by our Printer. + message.add_repeated_int32(42); // This will be printed as number. + + TextFormat::Printer printer; + EXPECT_TRUE(printer.RegisterFieldValuePrinter( + message.GetDescriptor()->FindFieldByName("optional_int32"), + new CustomInt32FieldValuePrinter())); + string text; + printer.PrintToString(message, &text); + EXPECT_EQ("optional_int32: value-is(42)\nrepeated_int32: 42\n", text); +} + +TEST_F(TextFormatTest, ErrorCasesRegisteringFieldValuePrinterShouldFail) { + protobuf_unittest::TestAllTypes message; + TextFormat::Printer printer; + // NULL printer. + EXPECT_FALSE(printer.RegisterFieldValuePrinter( + message.GetDescriptor()->FindFieldByName("optional_int32"), + NULL)); + // Because registration fails, the ownership of this printer is never taken. + TextFormat::FieldValuePrinter my_field_printer; + // NULL field + EXPECT_FALSE(printer.RegisterFieldValuePrinter(NULL, &my_field_printer)); +} + +class CustomMessageFieldValuePrinter : public TextFormat::FieldValuePrinter { + public: + virtual string PrintInt32(int32 v) const { + return StrCat(FieldValuePrinter::PrintInt32(v), " # x", ToHex(v)); + } + + virtual string PrintMessageStart(const Message& message, + int field_index, + int field_count, + bool single_line_mode) const { + if (single_line_mode) { + return " { "; + } + return StrCat( + " { # ", message.GetDescriptor()->name(), ": ", field_index, "\n"); + } +}; + +TEST_F(TextFormatTest, CustomPrinterForComments) { + protobuf_unittest::TestAllTypes message; + message.mutable_optional_nested_message(); + message.mutable_optional_import_message()->set_d(42); + message.add_repeated_nested_message(); + message.add_repeated_nested_message(); + message.add_repeated_import_message()->set_d(43); + message.add_repeated_import_message()->set_d(44); + TextFormat::Printer printer; + CustomMessageFieldValuePrinter my_field_printer; + printer.SetDefaultFieldValuePrinter(new CustomMessageFieldValuePrinter()); + string text; + printer.PrintToString(message, &text); + EXPECT_EQ( + "optional_nested_message { # NestedMessage: -1\n" + "}\n" + "optional_import_message { # ImportMessage: -1\n" + " d: 42 # x2a\n" + "}\n" + "repeated_nested_message { # NestedMessage: 0\n" + "}\n" + "repeated_nested_message { # NestedMessage: 1\n" + "}\n" + "repeated_import_message { # ImportMessage: 0\n" + " d: 43 # x2b\n" + "}\n" + "repeated_import_message { # ImportMessage: 1\n" + " d: 44 # x2c\n" + "}\n", + text); +} + +class CustomMultilineCommentPrinter : public TextFormat::FieldValuePrinter { + public: + virtual string PrintMessageStart(const Message& message, + int field_index, + int field_count, + bool single_line_comment) const { + return StrCat(" { # 1\n", " # 2\n"); + } +}; + +TEST_F(TextFormatTest, CustomPrinterForMultilineComments) { + protobuf_unittest::TestAllTypes message; + message.mutable_optional_nested_message(); + message.mutable_optional_import_message()->set_d(42); + TextFormat::Printer printer; + CustomMessageFieldValuePrinter my_field_printer; + printer.SetDefaultFieldValuePrinter(new CustomMultilineCommentPrinter()); + string text; + printer.PrintToString(message, &text); + EXPECT_EQ( + "optional_nested_message { # 1\n" + " # 2\n" + "}\n" + "optional_import_message { # 1\n" + " # 2\n" + " d: 42\n" + "}\n", + text); +} + TEST_F(TextFormatTest, ParseBasic) { io::ArrayInputStream input_stream(proto_debug_string_.data(), proto_debug_string_.size()); @@ -353,6 +542,25 @@ TEST_F(TextFormatExtensionsTest, ParseExtensions) { TestUtil::ExpectAllExtensionsSet(proto_); } +TEST_F(TextFormatTest, ParseEnumFieldFromNumber) { + // Create a parse string with a numerical value for an enum field. + string parse_string = strings::Substitute("optional_nested_enum: $0", + unittest::TestAllTypes::BAZ); + EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto_)); + EXPECT_TRUE(proto_.has_optional_nested_enum()); + EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.optional_nested_enum()); +} + +TEST_F(TextFormatTest, ParseEnumFieldFromNegativeNumber) { + ASSERT_LT(unittest::SPARSE_E, 0); + string parse_string = strings::Substitute("sparse_enum: $0", + unittest::SPARSE_E); + unittest::SparseEnumMessage proto; + EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto)); + EXPECT_TRUE(proto.has_sparse_enum()); + EXPECT_EQ(unittest::SPARSE_E, proto.sparse_enum()); +} + TEST_F(TextFormatTest, ParseStringEscape) { // Create a parse string with escpaed characters in it. string parse_string = "optional_string: " @@ -406,6 +614,47 @@ TEST_F(TextFormatTest, ParseFloatWithSuffix) { EXPECT_EQ(1.0, proto_.optional_float()); } +TEST_F(TextFormatTest, ParseShortRepeatedForm) { + string parse_string = + // Mixed short-form and long-form are simply concatenated. + "repeated_int32: 1\n" + "repeated_int32: [456, 789]\n" + "repeated_nested_enum: [ FOO ,BAR, # comment\n" + " 3]\n" + // Note that while the printer won't print repeated strings in short-form, + // the parser will accept them. + "repeated_string: [ \"foo\", 'bar' ]\n" + // Repeated message + "repeated_nested_message: [ { bb: 1 }, { bb : 2 }]\n" + // Repeated group + "RepeatedGroup [{ a: 3 },{ a: 4 }]\n"; + + ASSERT_TRUE(TextFormat::ParseFromString(parse_string, &proto_)); + + ASSERT_EQ(3, proto_.repeated_int32_size()); + EXPECT_EQ(1, proto_.repeated_int32(0)); + EXPECT_EQ(456, proto_.repeated_int32(1)); + EXPECT_EQ(789, proto_.repeated_int32(2)); + + ASSERT_EQ(3, proto_.repeated_nested_enum_size()); + EXPECT_EQ(unittest::TestAllTypes::FOO, proto_.repeated_nested_enum(0)); + EXPECT_EQ(unittest::TestAllTypes::BAR, proto_.repeated_nested_enum(1)); + EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.repeated_nested_enum(2)); + + ASSERT_EQ(2, proto_.repeated_string_size()); + EXPECT_EQ("foo", proto_.repeated_string(0)); + EXPECT_EQ("bar", proto_.repeated_string(1)); + + ASSERT_EQ(2, proto_.repeated_nested_message_size()); + EXPECT_EQ(1, proto_.repeated_nested_message(0).bb()); + EXPECT_EQ(2, proto_.repeated_nested_message(1).bb()); + + ASSERT_EQ(2, proto_.repeatedgroup_size()); + EXPECT_EQ(3, proto_.repeatedgroup(0).a()); + EXPECT_EQ(4, proto_.repeatedgroup(1).a()); +} + + TEST_F(TextFormatTest, Comments) { // Test that comments are ignored. @@ -658,6 +907,27 @@ TEST_F(TextFormatTest, ParseExotic) { message.repeated_string(0)); } +TEST_F(TextFormatTest, PrintFieldsInIndexOrder) { + protobuf_unittest::TestFieldOrderings message; + // Fields are listed in index order instead of field number. + message.set_my_string("Test String"); // Field number 11 + message.set_my_int(12345); // Field number 1 + message.set_my_float(0.999); // Field number 101 + TextFormat::Printer printer; + string text; + + // By default, print in field number order. + printer.PrintToString(message, &text); + EXPECT_EQ("my_int: 12345\nmy_string: \"Test String\"\nmy_float: 0.999\n", + text); + + // Print in index order. + printer.SetPrintMessageFieldsInIndexOrder(true); + printer.PrintToString(message, &text); + EXPECT_EQ("my_string: \"Test String\"\nmy_int: 12345\nmy_float: 0.999\n", + text); +} + class TextFormatParserTest : public testing::Test { protected: void ExpectFailure(const string& input, const string& message, int line, @@ -676,11 +946,31 @@ class TextFormatParserTest : public testing::Test { TextFormat::Parser parser; MockErrorCollector error_collector; parser.RecordErrorsTo(&error_collector); - EXPECT_EQ(parser.ParseFromString(input, proto), expected_result); + EXPECT_EQ(expected_result, parser.ParseFromString(input, proto)) + << input << " -> " << proto->DebugString(); EXPECT_EQ(SimpleItoa(line) + ":" + SimpleItoa(col) + ": " + message + "\n", error_collector.text_); } + void ExpectSuccessAndTree(const string& input, Message* proto, + TextFormat::ParseInfoTree* info_tree) { + TextFormat::Parser parser; + MockErrorCollector error_collector; + parser.RecordErrorsTo(&error_collector); + parser.WriteLocationsTo(info_tree); + + EXPECT_TRUE(parser.ParseFromString(input, proto)); + } + + void ExpectLocation(TextFormat::ParseInfoTree* tree, + const Descriptor* d, const string& field_name, + int index, int line, int column) { + TextFormat::ParseLocation location = tree->GetLocation( + d->FindFieldByName(field_name), index); + EXPECT_EQ(line, location.line); + EXPECT_EQ(column, location.column); + } + // An error collector which simply concatenates all its errors into a big // block of text which can be checked. class MockErrorCollector : public io::ErrorCollector { @@ -702,6 +992,71 @@ class TextFormatParserTest : public testing::Test { }; }; +TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) { + scoped_ptr message(new unittest::TestAllTypes); + const Descriptor* d = message->GetDescriptor(); + + string stringData = + "optional_int32: 1\n" + "optional_int64: 2\n" + " optional_double: 2.4\n" + "repeated_int32: 5\n" + "repeated_int32: 10\n" + "optional_nested_message <\n" + " bb: 78\n" + ">\n" + "repeated_nested_message <\n" + " bb: 79\n" + ">\n" + "repeated_nested_message <\n" + " bb: 80\n" + ">"; + + + TextFormat::ParseInfoTree tree; + ExpectSuccessAndTree(stringData, message.get(), &tree); + + // Verify that the tree has the correct positions. + ExpectLocation(&tree, d, "optional_int32", -1, 0, 0); + ExpectLocation(&tree, d, "optional_int64", -1, 1, 0); + ExpectLocation(&tree, d, "optional_double", -1, 2, 2); + + ExpectLocation(&tree, d, "repeated_int32", 0, 3, 0); + ExpectLocation(&tree, d, "repeated_int32", 1, 4, 0); + + ExpectLocation(&tree, d, "optional_nested_message", -1, 5, 0); + ExpectLocation(&tree, d, "repeated_nested_message", 0, 8, 0); + ExpectLocation(&tree, d, "repeated_nested_message", 1, 11, 0); + + // Check for fields not set. For an invalid field, the location returned + // should be -1, -1. + ExpectLocation(&tree, d, "repeated_int64", 0, -1, -1); + ExpectLocation(&tree, d, "repeated_int32", 6, -1, -1); + ExpectLocation(&tree, d, "some_unknown_field", -1, -1, -1); + + // Verify inside the nested message. + const FieldDescriptor* nested_field = + d->FindFieldByName("optional_nested_message"); + + TextFormat::ParseInfoTree* nested_tree = + tree.GetTreeForNested(nested_field, -1); + ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 6, 2); + + // Verify inside another nested message. + nested_field = d->FindFieldByName("repeated_nested_message"); + nested_tree = tree.GetTreeForNested(nested_field, 0); + ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 9, 2); + + nested_tree = tree.GetTreeForNested(nested_field, 1); + ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 12, 2); + + // Verify a NULL tree for an unknown nested field. + TextFormat::ParseInfoTree* unknown_nested_tree = + tree.GetTreeForNested(nested_field, 2); + + EXPECT_EQ(NULL, unknown_nested_tree); +} + TEST_F(TextFormatParserTest, ParseFieldValueFromString) { scoped_ptr message(new unittest::TestAllTypes); const Descriptor* d = message->GetDescriptor(); @@ -712,6 +1067,12 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) { EXPECT_EQ(value, message->optional_##name()); \ EXPECT_TRUE(message->has_optional_##name()); +#define EXPECT_BOOL_FIELD(name, value, valuestring) \ + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); \ + EXPECT_TRUE(message->optional_##name() == value); \ + EXPECT_TRUE(message->has_optional_##name()); + #define EXPECT_FLOAT_FIELD(name, value, valuestring) \ EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ valuestring, d->FindFieldByName("optional_" #name), message.get())); \ @@ -769,12 +1130,20 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) { EXPECT_INVALID(fixed64, "1,2"); // bool - EXPECT_FIELD(bool, true, "true"); - EXPECT_FIELD(bool, false, "false"); - EXPECT_INVALID(bool, "1"); + EXPECT_BOOL_FIELD(bool, true, "true"); + EXPECT_BOOL_FIELD(bool, false, "false"); + EXPECT_BOOL_FIELD(bool, true, "1"); + EXPECT_BOOL_FIELD(bool, true, "t"); + EXPECT_BOOL_FIELD(bool, false, "0"); + EXPECT_BOOL_FIELD(bool, false, "f"); + EXPECT_FIELD(bool, true, "True"); + EXPECT_FIELD(bool, false, "False"); + EXPECT_INVALID(bool, "tRue"); + EXPECT_INVALID(bool, "faLse"); + EXPECT_INVALID(bool, "2"); + EXPECT_INVALID(bool, "-0"); EXPECT_INVALID(bool, "on"); EXPECT_INVALID(bool, "a"); - EXPECT_INVALID(bool, "True"); // float EXPECT_FIELD(float, 1, "1"); @@ -791,6 +1160,9 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) { EXPECT_DOUBLE_FIELD(double, 3e5, "3e5"); EXPECT_INVALID(double, "a"); EXPECT_INVALID(double, "1,2"); + // Rejects hex and oct numbers for a double field. + EXPECT_INVALID(double, "0xf"); + EXPECT_INVALID(double, "012"); // string EXPECT_FIELD(string, "hello", "\"hello\""); @@ -799,7 +1171,8 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) { // enum EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAR, "BAR"); - EXPECT_INVALID(nested_enum, "1"); // number not supported + EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAZ, + SimpleItoa(unittest::TestAllTypes::BAZ)); EXPECT_INVALID(nested_enum, "FOOBAR"); // message @@ -810,6 +1183,7 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) { EXPECT_INVALID(nested_message, "any"); #undef EXPECT_FIELD +#undef EXPECT_BOOL_FIELD #undef EXPECT_FLOAT_FIELD #undef EXPECT_DOUBLE_FIELD #undef EXPECT_INVALID @@ -820,7 +1194,7 @@ TEST_F(TextFormatParserTest, InvalidToken) { ExpectFailure("optional_bool: true\n-5\n", "Expected identifier.", 2, 1); - ExpectFailure("optional_bool: true;\n", "Expected identifier.", 1, 20); + ExpectFailure("optional_bool: true!\n", "Expected identifier.", 1, 20); ExpectFailure("\"some string\"", "Expected identifier.", 1, 1); } @@ -851,6 +1225,22 @@ TEST_F(TextFormatParserTest, InvalidCapitalization) { 1, 16); } +TEST_F(TextFormatParserTest, AllowIgnoreCapitalizationError) { + TextFormat::Parser parser; + protobuf_unittest::TestAllTypes proto; + + // These fields have a mismatching case. + EXPECT_FALSE(parser.ParseFromString("Optional_Double: 10.0", &proto)); + EXPECT_FALSE(parser.ParseFromString("oPtIoNaLgRoUp { a: 15 }", &proto)); + + // ... but are parsed correctly if we match case insensitive. + parser.AllowCaseInsensitiveField(true); + EXPECT_TRUE(parser.ParseFromString("Optional_Double: 10.0", &proto)); + EXPECT_EQ(10.0, proto.optional_double()); + EXPECT_TRUE(parser.ParseFromString("oPtIoNaLgRoUp { a: 15 }", &proto)); + EXPECT_EQ(15, proto.optionalgroup().a()); +} + TEST_F(TextFormatParserTest, InvalidFieldValues) { // Invalid values for a double/float field. ExpectFailure("optional_double: \"hello\"\n", "Expected double.", 1, 18); @@ -868,10 +1258,10 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { 1, 16); ExpectFailure("optional_int32: 0x80000000\n", "Integer out of range.", 1, 17); - ExpectFailure("optional_int32: -0x80000001\n", - "Integer out of range.", 1, 18); ExpectFailure("optional_int64: 0x8000000000000000\n", "Integer out of range.", 1, 17); + ExpectFailure("optional_int32: -0x80000001\n", + "Integer out of range.", 1, 18); ExpectFailure("optional_int64: -0x8000000000000001\n", "Integer out of range.", 1, 18); @@ -890,7 +1280,7 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { // Invalid values for a boolean field. ExpectFailure("optional_bool: \"hello\"\n", "Expected identifier.", 1, 16); - ExpectFailure("optional_bool: 5\n", "Expected identifier.", 1, 16); + ExpectFailure("optional_bool: 5\n", "Integer out of range.", 1, 16); ExpectFailure("optional_bool: -7.5\n", "Expected identifier.", 1, 16); ExpectFailure("optional_bool: !\n", "Expected identifier.", 1, 16); @@ -911,12 +1301,18 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { 1, 17); // Invalid values for an enumeration field. - ExpectFailure("optional_nested_enum: \"hello\"\n", "Expected identifier.", - 1, 23); - - ExpectFailure("optional_nested_enum: 5\n", "Expected identifier.", 1, 23); - ExpectFailure("optional_nested_enum: -7.5\n", "Expected identifier.", 1, 23); - ExpectFailure("optional_nested_enum: !\n", "Expected identifier.", 1, 23); + ExpectFailure("optional_nested_enum: \"hello\"\n", + "Expected integer or identifier.", 1, 23); + + // Valid token, but enum value is not defined. + ExpectFailure("optional_nested_enum: 5\n", + "Unknown enumeration value of \"5\" for field " + "\"optional_nested_enum\".", 2, 1); + // We consume the negative sign, so the error position starts one character + // later. + ExpectFailure("optional_nested_enum: -7.5\n", "Expected integer.", 1, 24); + ExpectFailure("optional_nested_enum: !\n", + "Expected integer or identifier.", 1, 23); ExpectFailure( "optional_nested_enum: grah\n", @@ -986,6 +1382,14 @@ TEST_F(TextFormatParserTest, MergeDuplicateOptional) { EXPECT_EQ(2, message.c()); } +TEST_F(TextFormatParserTest, ExplicitDelimiters) { + unittest::TestRequired message; + EXPECT_TRUE(TextFormat::ParseFromString("a:1,b:2;c:3", &message)); + EXPECT_EQ(1, message.a()); + EXPECT_EQ(2, message.b()); + EXPECT_EQ(3, message.c()); +} + TEST_F(TextFormatParserTest, PrintErrorsToStderr) { vector errors; @@ -1069,6 +1473,7 @@ TEST_F(TextFormatMessageSetTest, Deserialize) { EXPECT_EQ(2, descriptors.size()); } + } // namespace text_format_unittest } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto index d51fa1e..969684f 100644 --- a/src/google/protobuf/unittest.proto +++ b/src/google/protobuf/unittest.proto @@ -35,6 +35,12 @@ // A proto file we will use for unit testing. +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added +option java_generic_services = true; // auto-added +option py_generic_services = true; // auto-added + import "google/protobuf/unittest_import.proto"; // We don't put this in a package within proto2 because we need to make sure @@ -63,6 +69,7 @@ message TestAllTypes { FOO = 1; BAR = 2; BAZ = 3; + NEG = -1; // Intentionally negative. } // Singular @@ -97,6 +104,12 @@ message TestAllTypes { optional string optional_string_piece = 24 [ctype=STRING_PIECE]; optional string optional_cord = 25 [ctype=CORD]; + // Defined in unittest_import_public.proto + optional protobuf_unittest_import.PublicImportMessage + optional_public_import_message = 26; + + optional NestedMessage optional_lazy_message = 27 [lazy=true]; + // Repeated repeated int32 repeated_int32 = 31; repeated int64 repeated_int64 = 32; @@ -129,6 +142,8 @@ message TestAllTypes { repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; repeated string repeated_cord = 55 [ctype=CORD]; + repeated NestedMessage repeated_lazy_message = 57 [lazy=true]; + // Singular with defaults optional int32 default_int32 = 61 [default = 41 ]; optional int64 default_int64 = 62 [default = 42 ]; @@ -153,6 +168,20 @@ message TestAllTypes { optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"]; optional string default_cord = 85 [ctype=CORD,default="123"]; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + optional NestedTestAllTypes child = 1; + optional TestAllTypes payload = 2; } message TestDeprecatedFields { @@ -210,6 +239,12 @@ extend TestAllExtensions { optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE]; optional string optional_cord_extension = 25 [ctype=CORD]; + optional protobuf_unittest_import.PublicImportMessage + optional_public_import_message_extension = 26; + + optional TestAllTypes.NestedMessage + optional_lazy_message_extension = 27 [lazy=true]; + // Repeated repeated int32 repeated_int32_extension = 31; repeated int64 repeated_int64_extension = 32; @@ -244,6 +279,9 @@ extend TestAllExtensions { repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE]; repeated string repeated_cord_extension = 55 [ctype=CORD]; + repeated TestAllTypes.NestedMessage + repeated_lazy_message_extension = 57 [lazy=true]; + // Singular with defaults optional int32 default_int32_extension = 61 [default = 41 ]; optional int64 default_int64_extension = 62 [default = 42 ]; @@ -271,6 +309,12 @@ extend TestAllExtensions { optional string default_string_piece_extension = 84 [ctype=STRING_PIECE, default="abc"]; optional string default_cord_extension = 85 [ctype=CORD, default="123"]; + + // For oneof test + optional uint32 oneof_uint32_extension = 111; + optional TestAllTypes.NestedMessage oneof_nested_message_extension = 112; + optional string oneof_string_extension = 113; + optional bytes oneof_bytes_extension = 114; } message TestNestedExtension { @@ -278,6 +322,9 @@ message TestNestedExtension { // Check for bug where string extensions declared in tested scope did not // compile. optional string test = 1002 [default="test"]; + // Used to test if generated extension name is correct when there are + // underscores. + optional string nested_string_extension = 1003; } } @@ -391,6 +438,13 @@ message TestDupFieldNumber { // NO_PROTO1 optional group Bar = 3 { optional int32 a = 1; } // NO_PROTO1 } // NO_PROTO1 +// Additional messages for testing lazy fields. +message TestEagerMessage { + optional TestAllTypes sub_message = 1 [lazy=false]; +} +message TestLazyMessage { + optional TestAllTypes sub_message = 1 [lazy=true]; +} // Needed for a Python test. message TestNestedMessageHasBits { @@ -404,6 +458,8 @@ message TestNestedMessageHasBits { // Test an enum that has multiple values with the same number. enum TestEnumWithDupValue { + option allow_alias = true; + FOO1 = 1; BAR1 = 2; BAZ = 3; @@ -464,6 +520,8 @@ message TestExtremeDefaultValues { optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF]; optional int32 small_int32 = 4 [default = -0x7FFFFFFF]; optional int64 small_int64 = 5 [default = -0x7FFFFFFFFFFFFFFF]; + optional int32 really_small_int32 = 21 [default = -0x80000000]; + optional int64 really_small_int64 = 22 [default = -0x8000000000000000]; // The default value here is UTF-8 for "\u1234". (We could also just type // the UTF-8 text directly into this text file rather than escape it, but @@ -487,6 +545,26 @@ message TestExtremeDefaultValues { optional float inf_float = 17 [default = inf]; optional float neg_inf_float = 18 [default = -inf]; optional float nan_float = 19 [default = nan]; + + // Tests for C++ trigraphs. + // Trigraphs should be escaped in C++ generated files, but they should not be + // escaped for other languages. + // Note that in .proto file, "\?" is a valid way to escape ? in string + // literals. + optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"]; + + // String defaults containing the character '\000' + optional string string_with_zero = 23 [default = "hel\000lo"]; + optional bytes bytes_with_zero = 24 [default = "wor\000ld"]; + optional string string_piece_with_zero = 25 [ctype=STRING_PIECE, + default="ab\000c"]; + optional string cord_with_zero = 26 [ctype=CORD, + default="12\0003"]; + optional string replacement_string = 27 [default="${unknown}"]; +} + +message SparseEnumMessage { + optional TestSparseEnum sparse_enum = 1; } // Test String and Bytes: string is for valid UTF-8 strings @@ -494,10 +572,113 @@ message OneString { optional string data = 1; } +message MoreString { + repeated string data = 1; +} + message OneBytes { optional bytes data = 1; } +message MoreBytes { + repeated bytes data = 1; +} + +// Test int32, uint32, int64, uint64, and bool are all compatible +message Int32Message { + optional int32 data = 1; +} + +message Uint32Message { + optional uint32 data = 1; +} + +message Int64Message { + optional int64 data = 1; +} + +message Uint64Message { + optional uint64 data = 1; +} + +message BoolMessage { + optional bool data = 1; +} + +// Test oneofs. +message TestOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + TestAllTypes foo_message = 3; + group FooGroup = 4 { + optional int32 a = 5; + optional string b = 6; + } + } +} + +message TestOneofBackwardsCompatible { + optional int32 foo_int = 1; + optional string foo_string = 2; + optional TestAllTypes foo_message = 3; + optional group FooGroup = 4 { + optional int32 a = 5; + optional string b = 6; + } +} + +message TestOneof2 { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + string foo_cord = 3 [ctype=CORD]; + string foo_string_piece = 4 [ctype=STRING_PIECE]; + bytes foo_bytes = 5; + NestedEnum foo_enum = 6; + NestedMessage foo_message = 7; + group FooGroup = 8 { + optional int32 a = 9; + optional string b = 10; + } + NestedMessage foo_lazy_message = 11 [lazy=true]; + } + + oneof bar { + int32 bar_int = 12 [default = 5]; + string bar_string = 13 [default = "STRING"]; + string bar_cord = 14 [ctype=CORD, default = "CORD"]; + string bar_string_piece = 15 [ctype=STRING_PIECE, default = "SPIECE"]; + bytes bar_bytes = 16 [default = "BYTES"]; + NestedEnum bar_enum = 17 [default = BAR]; + } + + optional int32 baz_int = 18; + optional string baz_string = 19 [default = "BAZ"]; + + message NestedMessage { + optional int64 qux_int = 1; + repeated int32 corge_int = 2; + } + + enum NestedEnum { + FOO = 1; + BAR = 2; + BAZ = 3; + } +} + +message TestRequiredOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + NestedMessage foo_message = 3; + } + message NestedMessage { + required double required_double = 1; + } +} + // Test messages for packed fields message TestPackedTypes { @@ -557,6 +738,27 @@ extend TestPackedExtensions { repeated ForeignEnum packed_enum_extension = 103 [packed = true]; } +message TestUnpackedExtensions { + extensions 1 to max; +} + +extend TestUnpackedExtensions { + repeated int32 unpacked_int32_extension = 90 [packed = false]; + repeated int64 unpacked_int64_extension = 91 [packed = false]; + repeated uint32 unpacked_uint32_extension = 92 [packed = false]; + repeated uint64 unpacked_uint64_extension = 93 [packed = false]; + repeated sint32 unpacked_sint32_extension = 94 [packed = false]; + repeated sint64 unpacked_sint64_extension = 95 [packed = false]; + repeated fixed32 unpacked_fixed32_extension = 96 [packed = false]; + repeated fixed64 unpacked_fixed64_extension = 97 [packed = false]; + repeated sfixed32 unpacked_sfixed32_extension = 98 [packed = false]; + repeated sfixed64 unpacked_sfixed64_extension = 99 [packed = false]; + repeated float unpacked_float_extension = 100 [packed = false]; + repeated double unpacked_double_extension = 101 [packed = false]; + repeated bool unpacked_bool_extension = 102 [packed = false]; + repeated ForeignEnum unpacked_enum_extension = 103 [packed = false]; +} + // Used by ExtensionSetTest/DynamicExtensions. The test actually builds // a set of extensions to TestAllExtensions dynamically, based on the fields // of this message type. @@ -598,10 +800,56 @@ message TestRepeatedScalarDifferentTagSizes { repeated uint64 repeated_uint64 = 262143; } +// Test that if an optional or required message/group field appears multiple +// times in the input, they need to be merged. +message TestParsingMerge { + // RepeatedFieldsGenerator defines matching field types as TestParsingMerge, + // except that all fields are repeated. In the tests, we will serialize the + // RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge. + // Repeated fields in RepeatedFieldsGenerator are expected to be merged into + // the corresponding required/optional fields in TestParsingMerge. + message RepeatedFieldsGenerator { + repeated TestAllTypes field1 = 1; + repeated TestAllTypes field2 = 2; + repeated TestAllTypes field3 = 3; + repeated group Group1 = 10 { + optional TestAllTypes field1 = 11; + } + repeated group Group2 = 20 { + optional TestAllTypes field1 = 21; + } + repeated TestAllTypes ext1 = 1000; + repeated TestAllTypes ext2 = 1001; + } + required TestAllTypes required_all_types = 1; + optional TestAllTypes optional_all_types = 2; + repeated TestAllTypes repeated_all_types = 3; + optional group OptionalGroup = 10 { + optional TestAllTypes optional_group_all_types = 11; + } + repeated group RepeatedGroup = 20 { + optional TestAllTypes repeated_group_all_types = 21; + } + extensions 1000 to max; + extend TestParsingMerge { + optional TestAllTypes optional_ext = 1000; + repeated TestAllTypes repeated_ext = 1001; + } +} + +message TestCommentInjectionMessage { + // */ <- This should not close the generated doc comment + optional string a = 1 [default="*/ <- Neither should this."]; +} + + // Test that RPC services work. message FooRequest {} message FooResponse {} +message FooClientMessage {} +message FooServerMessage{} + service TestService { rpc Foo(FooRequest) returns (FooResponse); rpc Bar(BarRequest) returns (BarResponse); @@ -610,3 +858,4 @@ service TestService { message BarRequest {} message BarResponse {} + diff --git a/src/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto index b6ee03d..52ee6c7 100644 --- a/src/google/protobuf/unittest_custom_options.proto +++ b/src/google/protobuf/unittest_custom_options.proto @@ -35,6 +35,12 @@ // A proto file used to test the "custom options" feature of proto2. +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added +option java_generic_services = true; // auto-added +option py_generic_services = true; + // A custom file option (defined below). option (file_opt1) = 9876543210; @@ -110,6 +116,12 @@ message CustomOptionFooRequest { message CustomOptionFooResponse { } +message CustomOptionFooClientMessage { +} + +message CustomOptionFooServerMessage { +} + service TestServiceWithCustomOptions { option (service_opt1) = -9876543210; @@ -206,6 +218,7 @@ message ComplexOptionType1 { optional int32 foo = 1; optional int32 foo2 = 2; optional int32 foo3 = 3; + repeated int32 foo4 = 4; extensions 100 to max; } @@ -223,6 +236,7 @@ message ComplexOptionType2 { } optional ComplexOptionType4 fred = 3; + repeated ComplexOptionType4 barney = 4; extensions 100 to max; } @@ -259,6 +273,8 @@ message VariousComplexOptions { option (.protobuf_unittest.complex_opt1).foo = 42; option (protobuf_unittest.complex_opt1).(.protobuf_unittest.quux) = 324; option (.protobuf_unittest.complex_opt1).(protobuf_unittest.corge).qux = 876; + option (protobuf_unittest.complex_opt1).foo4 = 99; + option (protobuf_unittest.complex_opt1).foo4 = 88; option (complex_opt2).baz = 987; option (complex_opt2).(grault) = 654; option (complex_opt2).bar.foo = 743; @@ -269,7 +285,109 @@ message VariousComplexOptions { option (complex_opt2).(protobuf_unittest.garply).(corge).qux = 2121; option (ComplexOptionType2.ComplexOptionType4.complex_opt4).waldo = 1971; option (complex_opt2).fred.waldo = 321; + option (complex_opt2).barney = { waldo: 101 }; + option (complex_opt2).barney = { waldo: 212 }; option (protobuf_unittest.complex_opt3).qux = 9; option (complex_opt3).complexoptiontype5.plugh = 22; option (complexopt6).xyzzy = 24; } + +// ------------------------------------------------------ +// Definitions for testing aggregate option parsing. +// See descriptor_unittest.cc. + +message AggregateMessageSet { + option message_set_wire_format = true; + extensions 4 to max; +} + +message AggregateMessageSetElement { + extend AggregateMessageSet { + optional AggregateMessageSetElement message_set_extension = 15447542; + } + optional string s = 1; +} + +// A helper type used to test aggregate option parsing +message Aggregate { + optional int32 i = 1; + optional string s = 2; + + // A nested object + optional Aggregate sub = 3; + + // To test the parsing of extensions inside aggregate values + optional google.protobuf.FileOptions file = 4; + extend google.protobuf.FileOptions { + optional Aggregate nested = 15476903; + } + + // An embedded message set + optional AggregateMessageSet mset = 5; +} + +// Allow Aggregate to be used as an option at all possible locations +// in the .proto grammer. +extend google.protobuf.FileOptions { optional Aggregate fileopt = 15478479; } +extend google.protobuf.MessageOptions { optional Aggregate msgopt = 15480088; } +extend google.protobuf.FieldOptions { optional Aggregate fieldopt = 15481374; } +extend google.protobuf.EnumOptions { optional Aggregate enumopt = 15483218; } +extend google.protobuf.EnumValueOptions { optional Aggregate enumvalopt = 15486921; } +extend google.protobuf.ServiceOptions { optional Aggregate serviceopt = 15497145; } +extend google.protobuf.MethodOptions { optional Aggregate methodopt = 15512713; } + +// Try using AggregateOption at different points in the proto grammar +option (fileopt) = { + s: 'FileAnnotation' + // Also test the handling of comments + /* of both types */ i: 100 + + sub { s: 'NestedFileAnnotation' } + + // Include a google.protobuf.FileOptions and recursively extend it with + // another fileopt. + file { + [protobuf_unittest.fileopt] { + s:'FileExtensionAnnotation' + } + } + + // A message set inside an option value + mset { + [protobuf_unittest.AggregateMessageSetElement.message_set_extension] { + s: 'EmbeddedMessageSetElement' + } + } +}; + +message AggregateMessage { + option (msgopt) = { i:101 s:'MessageAnnotation' }; + optional int32 fieldname = 1 [(fieldopt) = { s:'FieldAnnotation' }]; +} + +service AggregateService { + option (serviceopt) = { s:'ServiceAnnotation' }; + rpc Method (AggregateMessage) returns (AggregateMessage) { + option (methodopt) = { s:'MethodAnnotation' }; + } +} + +enum AggregateEnum { + option (enumopt) = { s:'EnumAnnotation' }; + VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }]; +} + +// Test custom options for nested type. +message NestedOptionType { + message NestedMessage { + option (message_opt1) = 1001; + optional int32 nested_field = 1 [(field_opt1) = 1002]; + } + enum NestedEnum { + option (enum_opt1) = 1003; + NESTED_ENUM_VALUE = 1 [(enum_value_opt1) = 1004]; + } + extend google.protobuf.FileOptions { + optional int32 nested_extension = 7912573 [(field_opt2) = 1005]; + } +} diff --git a/src/google/protobuf/unittest_import.proto b/src/google/protobuf/unittest_import.proto index cd533ec..c115b11 100644 --- a/src/google/protobuf/unittest_import.proto +++ b/src/google/protobuf/unittest_import.proto @@ -49,6 +49,9 @@ option java_package = "com.google.protobuf.test"; // Do not set a java_outer_classname here to verify that Proto2 works without // one. +// Test public import +import public "google/protobuf/unittest_import_public.proto"; + message ImportMessage { optional int32 d = 1; } diff --git a/src/google/protobuf/unittest_import_lite.proto b/src/google/protobuf/unittest_import_lite.proto index ebaab5c..81b117f 100644 --- a/src/google/protobuf/unittest_import_lite.proto +++ b/src/google/protobuf/unittest_import_lite.proto @@ -38,6 +38,8 @@ option optimize_for = LITE_RUNTIME; option java_package = "com.google.protobuf"; +import public "google/protobuf/unittest_import_public_lite.proto"; + message ImportMessageLite { optional int32 d = 1; } diff --git a/src/google/protobuf/unittest_import_public.proto b/src/google/protobuf/unittest_import_public.proto new file mode 100644 index 0000000..ea5d1b1 --- /dev/null +++ b/src/google/protobuf/unittest_import_public.proto @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: liujisi@google.com (Pherl Liu) + + +package protobuf_unittest_import; + +option java_package = "com.google.protobuf.test"; + +message PublicImportMessage { + optional int32 e = 1; +} diff --git a/src/google/protobuf/unittest_import_public_lite.proto b/src/google/protobuf/unittest_import_public_lite.proto new file mode 100644 index 0000000..d077563 --- /dev/null +++ b/src/google/protobuf/unittest_import_public_lite.proto @@ -0,0 +1,42 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: liujisi@google.com (Pherl Liu) + + +package protobuf_unittest_import; + +option optimize_for = LITE_RUNTIME; + +option java_package = "com.google.protobuf"; + +message PublicImportMessageLite { + optional int32 e = 1; +} diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto index cca6b49..ffff012 100644 --- a/src/google/protobuf/unittest_lite.proto +++ b/src/google/protobuf/unittest_lite.proto @@ -85,6 +85,12 @@ message TestAllTypesLite { optional string optional_string_piece = 24 [ctype=STRING_PIECE]; optional string optional_cord = 25 [ctype=CORD]; + // Defined in unittest_import_public.proto + optional protobuf_unittest_import.PublicImportMessageLite + optional_public_import_message = 26; + + optional NestedMessage optional_lazy_message = 27 [lazy=true]; + // Repeated repeated int32 repeated_int32 = 31; repeated int64 repeated_int64 = 32; @@ -118,6 +124,8 @@ message TestAllTypesLite { repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; repeated string repeated_cord = 55 [ctype=CORD]; + repeated NestedMessage repeated_lazy_message = 57 [lazy=true]; + // Singular with defaults optional int32 default_int32 = 61 [default = 41 ]; optional int64 default_int64 = 62 [default = 42 ]; @@ -143,6 +151,14 @@ message TestAllTypesLite { optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"]; optional string default_cord = 85 [ctype=CORD,default="123"]; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } } message ForeignMessageLite { @@ -213,6 +229,12 @@ extend TestAllExtensionsLite { [ctype=STRING_PIECE]; optional string optional_cord_extension_lite = 25 [ctype=CORD]; + optional protobuf_unittest_import.PublicImportMessageLite + optional_public_import_message_extension_lite = 26; + + optional TestAllTypesLite.NestedMessage + optional_lazy_message_extension_lite = 27 [lazy=true]; + // Repeated repeated int32 repeated_int32_extension_lite = 31; repeated int64 repeated_int64_extension_lite = 32; @@ -249,6 +271,9 @@ extend TestAllExtensionsLite { [ctype=STRING_PIECE]; repeated string repeated_cord_extension_lite = 55 [ctype=CORD]; + repeated TestAllTypesLite.NestedMessage + repeated_lazy_message_extension_lite = 57 [lazy=true]; + // Singular with defaults optional int32 default_int32_extension_lite = 61 [default = 41 ]; optional int64 default_int64_extension_lite = 62 [default = 42 ]; @@ -276,6 +301,12 @@ extend TestAllExtensionsLite { optional string default_string_piece_extension_lite = 84 [ctype=STRING_PIECE, default="abc"]; optional string default_cord_extension_lite = 85 [ctype=CORD, default="123"]; + + // For oneof test + optional uint32 oneof_uint32_extension_lite = 111; + optional TestAllTypesLite.NestedMessage oneof_nested_message_extension_lite = 112; + optional string oneof_string_extension_lite = 113; + optional bytes oneof_bytes_extension_lite = 114; } message TestPackedExtensionsLite { @@ -310,3 +341,44 @@ message TestNestedExtensionLite { message TestDeprecatedLite { optional int32 deprecated_field = 1 [deprecated = true]; } + +// See the comments of the same type in unittest.proto. +message TestParsingMergeLite { + message RepeatedFieldsGenerator { + repeated TestAllTypesLite field1 = 1; + repeated TestAllTypesLite field2 = 2; + repeated TestAllTypesLite field3 = 3; + repeated group Group1 = 10 { + optional TestAllTypesLite field1 = 11; + } + repeated group Group2 = 20 { + optional TestAllTypesLite field1 = 21; + } + repeated TestAllTypesLite ext1 = 1000; + repeated TestAllTypesLite ext2 = 1001; + } + required TestAllTypesLite required_all_types = 1; + optional TestAllTypesLite optional_all_types = 2; + repeated TestAllTypesLite repeated_all_types = 3; + optional group OptionalGroup = 10 { + optional TestAllTypesLite optional_group_all_types = 11; + } + repeated group RepeatedGroup = 20 { + optional TestAllTypesLite repeated_group_all_types = 21; + } + extensions 1000 to max; + extend TestParsingMergeLite { + optional TestAllTypesLite optional_ext = 1000; + repeated TestAllTypesLite repeated_ext = 1001; + } +} + +// TestEmptyMessageLite is used to test unknown fields support in lite mode. +message TestEmptyMessageLite{ +} + +// Like above, but declare all field numbers as potential extensions. No +// actual extensions should ever be defined for this type. +message TestEmptyMessageWithExtensionsLite { + extensions 1 to max; +} diff --git a/src/google/protobuf/unittest_mset.proto b/src/google/protobuf/unittest_mset.proto index 3497f09..1d32559 100644 --- a/src/google/protobuf/unittest_mset.proto +++ b/src/google/protobuf/unittest_mset.proto @@ -62,6 +62,17 @@ message TestMessageSetExtension2 { optional string str = 25; } +// This message was used to generate +// //net/proto2/python/internal/testdata/message_set_message, but is commented +// out since it must not actually exist in code, to simulate an "unknown" +// extension. +// message TestMessageSetUnknownExtension { +// extend TestMessageSet { +// optional TestMessageSetUnknownExtension message_set_extension = 56141421; +// } +// optional int64 a = 1; +// } + // MessageSet wire format is equivalent to this. message RawMessageSet { repeated group Item = 1 { diff --git a/src/google/protobuf/unittest_no_generic_services.proto b/src/google/protobuf/unittest_no_generic_services.proto index fcae421..a414220 100644 --- a/src/google/protobuf/unittest_no_generic_services.proto +++ b/src/google/protobuf/unittest_no_generic_services.proto @@ -32,9 +32,8 @@ package google.protobuf.no_generic_services_test; -option cc_generic_services = false; -option java_generic_services = false; -option py_generic_services = false; + +// *_generic_services are false by default. message TestMessage { optional int32 a = 1; diff --git a/src/google/protobuf/unittest_optimize_for.proto b/src/google/protobuf/unittest_optimize_for.proto index feecbef..541d47f 100644 --- a/src/google/protobuf/unittest_optimize_for.proto +++ b/src/google/protobuf/unittest_optimize_for.proto @@ -50,12 +50,17 @@ message TestOptimizedForSize { optional int32 test_extension = 1234; optional TestRequiredOptimizedForSize test_extension2 = 1235; } + + oneof foo { + int32 integer_field = 2; + string string_field = 3; + } } message TestRequiredOptimizedForSize { required int32 x = 1; } - + message TestOptionalOptimizedForSize { optional TestRequiredOptimizedForSize o = 1; } diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc index e1f8b83..c0356af 100644 --- a/src/google/protobuf/unknown_field_set.cc +++ b/src/google/protobuf/unknown_field_set.cc @@ -32,19 +32,20 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include #include -#include + +#include #include #include #include #include +#include namespace google { namespace protobuf { UnknownFieldSet::UnknownFieldSet() - : fields_(NULL) {} + : fields_(NULL) {} UnknownFieldSet::~UnknownFieldSet() { Clear(); @@ -59,6 +60,14 @@ void UnknownFieldSet::ClearFallback() { fields_->clear(); } +void UnknownFieldSet::ClearAndFreeMemory() { + if (fields_ != NULL) { + Clear(); + delete fields_; + fields_ = NULL; + } +} + void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) { for (int i = 0; i < other.field_count(); i++) { AddField(other.field(i)); @@ -73,8 +82,9 @@ int UnknownFieldSet::SpaceUsedExcludingSelf() const { const UnknownField& field = (*fields_)[i]; switch (field.type()) { case UnknownField::TYPE_LENGTH_DELIMITED: - total_size += sizeof(*field.length_delimited_) + - internal::StringSpaceUsedExcludingSelf(*field.length_delimited_); + total_size += sizeof(*field.length_delimited_.string_value_) + + internal::StringSpaceUsedExcludingSelf( + *field.length_delimited_.string_value_); break; case UnknownField::TYPE_GROUP: total_size += field.group_->SpaceUsed(); @@ -94,7 +104,7 @@ void UnknownFieldSet::AddVarint(int number, uint64 value) { if (fields_ == NULL) fields_ = new vector; UnknownField field; field.number_ = number; - field.type_ = UnknownField::TYPE_VARINT; + field.SetType(UnknownField::TYPE_VARINT); field.varint_ = value; fields_->push_back(field); } @@ -103,7 +113,7 @@ void UnknownFieldSet::AddFixed32(int number, uint32 value) { if (fields_ == NULL) fields_ = new vector; UnknownField field; field.number_ = number; - field.type_ = UnknownField::TYPE_FIXED32; + field.SetType(UnknownField::TYPE_FIXED32); field.fixed32_ = value; fields_->push_back(field); } @@ -112,7 +122,7 @@ void UnknownFieldSet::AddFixed64(int number, uint64 value) { if (fields_ == NULL) fields_ = new vector; UnknownField field; field.number_ = number; - field.type_ = UnknownField::TYPE_FIXED64; + field.SetType(UnknownField::TYPE_FIXED64); field.fixed64_ = value; fields_->push_back(field); } @@ -121,17 +131,18 @@ string* UnknownFieldSet::AddLengthDelimited(int number) { if (fields_ == NULL) fields_ = new vector; UnknownField field; field.number_ = number; - field.type_ = UnknownField::TYPE_LENGTH_DELIMITED; - field.length_delimited_ = new string; + field.SetType(UnknownField::TYPE_LENGTH_DELIMITED); + field.length_delimited_.string_value_ = new string; fields_->push_back(field); - return field.length_delimited_; + return field.length_delimited_.string_value_; } + UnknownFieldSet* UnknownFieldSet::AddGroup(int number) { if (fields_ == NULL) fields_ = new vector; UnknownField field; field.number_ = number; - field.type_ = UnknownField::TYPE_GROUP; + field.SetType(UnknownField::TYPE_GROUP); field.group_ = new UnknownFieldSet; fields_->push_back(field); return field.group_; @@ -143,11 +154,43 @@ void UnknownFieldSet::AddField(const UnknownField& field) { fields_->back().DeepCopy(); } -bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) { +void UnknownFieldSet::DeleteSubrange(int start, int num) { + GOOGLE_DCHECK(fields_ != NULL); + // Delete the specified fields. + for (int i = 0; i < num; ++i) { + (*fields_)[i + start].Delete(); + } + // Slide down the remaining fields. + for (int i = start + num; i < fields_->size(); ++i) { + (*fields_)[i - num] = (*fields_)[i]; + } + // Pop off the # of deleted fields. + for (int i = 0; i < num; ++i) { + fields_->pop_back(); + } +} + +void UnknownFieldSet::DeleteByNumber(int number) { + if (fields_ == NULL) return; + int left = 0; // The number of fields left after deletion. + for (int i = 0; i < fields_->size(); ++i) { + UnknownField* field = &(*fields_)[i]; + if (field->number() == number) { + field->Delete(); + } else { + if (i != left) { + (*fields_)[left] = (*fields_)[i]; + } + ++left; + } + } + fields_->resize(left); +} +bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) { UnknownFieldSet other; if (internal::WireFormat::SkipMessage(input, &other) && - input->ConsumedEntireMessage()) { + input->ConsumedEntireMessage()) { MergeFrom(other); return true; } else { @@ -162,8 +205,8 @@ bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) { bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { io::CodedInputStream coded_input(input); - return ParseFromCodedStream(&coded_input) && - coded_input.ConsumedEntireMessage(); + return (ParseFromCodedStream(&coded_input) && + coded_input.ConsumedEntireMessage()); } bool UnknownFieldSet::ParseFromArray(const void* data, int size) { @@ -174,7 +217,7 @@ bool UnknownFieldSet::ParseFromArray(const void* data, int size) { void UnknownField::Delete() { switch (type()) { case UnknownField::TYPE_LENGTH_DELIMITED: - delete length_delimited_; + delete length_delimited_.string_value_; break; case UnknownField::TYPE_GROUP: delete group_; @@ -187,7 +230,8 @@ void UnknownField::Delete() { void UnknownField::DeepCopy() { switch (type()) { case UnknownField::TYPE_LENGTH_DELIMITED: - length_delimited_ = new string(*length_delimited_); + length_delimited_.string_value_ = new string( + *length_delimited_.string_value_); break; case UnknownField::TYPE_GROUP: { UnknownFieldSet* group = new UnknownFieldSet; @@ -200,5 +244,22 @@ void UnknownField::DeepCopy() { } } + +void UnknownField::SerializeLengthDelimitedNoTag( + io::CodedOutputStream* output) const { + GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type()); + const string& data = *length_delimited_.string_value_; + output->WriteVarint32(data.size()); + output->WriteRawMaybeAliased(data.data(), data.size()); +} + +uint8* UnknownField::SerializeLengthDelimitedNoTagToArray(uint8* target) const { + GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type()); + const string& data = *length_delimited_.string_value_; + target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target); + target = io::CodedOutputStream::WriteStringToArray(data, target); + return target; +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h index 84c2e2b..db26abe 100644 --- a/src/google/protobuf/unknown_field_set.h +++ b/src/google/protobuf/unknown_field_set.h @@ -38,12 +38,23 @@ #ifndef GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__ #define GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__ +#include #include #include -#include +#include namespace google { namespace protobuf { + namespace io { + class CodedInputStream; // coded_stream.h + class CodedOutputStream; // coded_stream.h + class ZeroCopyInputStream; // zero_copy_stream.h + } + namespace internal { + class WireFormat; // wire_format.h + class MessageSetFieldSkipperUsingCord; + // extension_set_heavy.cc + } class Message; // message.h class UnknownField; // below @@ -68,6 +79,9 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet { // Remove all fields. inline void Clear(); + // Remove all fields and deallocate internal data objects + void ClearAndFreeMemory(); + // Is this set empty? inline bool empty() const; @@ -107,6 +121,15 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet { // Adds an unknown field from another set. void AddField(const UnknownField& field); + // Delete fields with indices in the range [start .. start+num-1]. + // Caution: implementation moves all fields with indices [start+num .. ]. + void DeleteSubrange(int start, int num); + + // Delete all fields with a specific field number. The order of left fields + // is preserved. + // Caution: implementation moves all fields after the first deleted field. + void DeleteByNumber(int number); + // Parsing helpers ------------------------------------------------- // These work exactly like the similarly-named methods of Message. @@ -119,9 +142,10 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet { } private: + void ClearFallback(); - vector* fields_; + std::vector* fields_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet); }; @@ -159,6 +183,15 @@ class LIBPROTOBUF_EXPORT UnknownField { inline string* mutable_length_delimited(); inline UnknownFieldSet* mutable_group(); + // Serialization API. + // These methods can take advantage of the underlying implementation and may + // archieve a better performance than using getters to retrieve the data and + // do the serialization yourself. + void SerializeLengthDelimitedNoTag(io::CodedOutputStream* output) const; + uint8* SerializeLengthDelimitedNoTagToArray(uint8* target) const; + + inline int GetLengthDelimitedSize() const; + private: friend class UnknownFieldSet; @@ -168,13 +201,19 @@ class LIBPROTOBUF_EXPORT UnknownField { // Make a deep copy of any pointers in this UnknownField. void DeepCopy(); - unsigned int number_ : 29; - unsigned int type_ : 3; + // Set the wire type of this UnknownField. Should only be used when this + // UnknownField is being created. + inline void SetType(Type type); + + uint32 number_; + uint32 type_; union { uint64 varint_; uint32 fixed32_; uint64 fixed64_; - string* length_delimited_; + mutable union { + string* string_value_; + } length_delimited_; UnknownFieldSet* group_; }; }; @@ -211,57 +250,68 @@ inline void UnknownFieldSet::AddLengthDelimited( AddLengthDelimited(number)->assign(value); } + inline int UnknownField::number() const { return number_; } inline UnknownField::Type UnknownField::type() const { return static_cast(type_); } -inline uint64 UnknownField::varint () const { - GOOGLE_DCHECK_EQ(type_, TYPE_VARINT); +inline uint64 UnknownField::varint() const { + assert(type() == TYPE_VARINT); return varint_; } inline uint32 UnknownField::fixed32() const { - GOOGLE_DCHECK_EQ(type_, TYPE_FIXED32); + assert(type() == TYPE_FIXED32); return fixed32_; } inline uint64 UnknownField::fixed64() const { - GOOGLE_DCHECK_EQ(type_, TYPE_FIXED64); + assert(type() == TYPE_FIXED64); return fixed64_; } inline const string& UnknownField::length_delimited() const { - GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED); - return *length_delimited_; + assert(type() == TYPE_LENGTH_DELIMITED); + return *length_delimited_.string_value_; } inline const UnknownFieldSet& UnknownField::group() const { - GOOGLE_DCHECK_EQ(type_, TYPE_GROUP); + assert(type() == TYPE_GROUP); return *group_; } inline void UnknownField::set_varint(uint64 value) { - GOOGLE_DCHECK_EQ(type_, TYPE_VARINT); + assert(type() == TYPE_VARINT); varint_ = value; } inline void UnknownField::set_fixed32(uint32 value) { - GOOGLE_DCHECK_EQ(type_, TYPE_FIXED32); + assert(type() == TYPE_FIXED32); fixed32_ = value; } inline void UnknownField::set_fixed64(uint64 value) { - GOOGLE_DCHECK_EQ(type_, TYPE_FIXED64); + assert(type() == TYPE_FIXED64); fixed64_ = value; } inline void UnknownField::set_length_delimited(const string& value) { - GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED); - length_delimited_->assign(value); + assert(type() == TYPE_LENGTH_DELIMITED); + length_delimited_.string_value_->assign(value); } inline string* UnknownField::mutable_length_delimited() { - GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED); - return length_delimited_; + assert(type() == TYPE_LENGTH_DELIMITED); + return length_delimited_.string_value_; } inline UnknownFieldSet* UnknownField::mutable_group() { - GOOGLE_DCHECK_EQ(type_, TYPE_GROUP); + assert(type() == TYPE_GROUP); return group_; } +inline int UnknownField::GetLengthDelimitedSize() const { + GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type()); + return length_delimited_.string_value_->size(); +} + +inline void UnknownField::SetType(Type type) { + type_ = type; +} + + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc index 1235c9e..8e9bc84 100644 --- a/src/google/protobuf/unknown_field_set_unittest.cc +++ b/src/google/protobuf/unknown_field_set_unittest.cc @@ -46,15 +46,13 @@ #include #include #include -#include +#include namespace google { namespace protobuf { using internal::WireFormat; -namespace { - class UnknownFieldSetTest : public testing::Test { protected: virtual void SetUp() { @@ -107,6 +105,8 @@ class UnknownFieldSetTest : public testing::Test { UnknownFieldSet* unknown_fields_; }; +namespace { + TEST_F(UnknownFieldSetTest, AllFieldsPresent) { // All fields of TestAllTypes should be present, in numeric order (because // that's the order we parsed them in). Fields that are not valid field @@ -118,7 +118,12 @@ TEST_F(UnknownFieldSetTest, AllFieldsPresent) { const FieldDescriptor* field = descriptor_->FindFieldByNumber(i); if (field != NULL) { ASSERT_LT(pos, unknown_fields_->field_count()); - EXPECT_EQ(i, unknown_fields_->field(pos++).number()); + // Do not check oneof field if it is not set. + if (field->containing_oneof() == NULL) { + EXPECT_EQ(i, unknown_fields_->field(pos++).number()); + } else if (i == unknown_fields_->field(pos).number()) { + pos++; + } if (field->is_repeated()) { // Should have a second instance. ASSERT_LT(pos, unknown_fields_->field_count()); @@ -297,12 +302,21 @@ TEST_F(UnknownFieldSetTest, MergeFrom) { destination.DebugString()); } + TEST_F(UnknownFieldSetTest, Clear) { // Clear the set. empty_message_.Clear(); EXPECT_EQ(0, unknown_fields_->field_count()); } +TEST_F(UnknownFieldSetTest, ClearAndFreeMemory) { + EXPECT_GT(unknown_fields_->field_count(), 0); + unknown_fields_->ClearAndFreeMemory(); + EXPECT_EQ(0, unknown_fields_->field_count()); + unknown_fields_->AddVarint(123456, 654321); + EXPECT_EQ(1, unknown_fields_->field_count()); +} + TEST_F(UnknownFieldSetTest, ParseKnownAndUnknown) { // Test mixing known and unknown fields when parsing. @@ -498,6 +512,7 @@ TEST_F(UnknownFieldSetTest, SpaceUsed) { EXPECT_LT(base_size, empty_message.SpaceUsed()); } + TEST_F(UnknownFieldSetTest, Empty) { UnknownFieldSet unknown_fields; EXPECT_TRUE(unknown_fields.empty()); @@ -507,6 +522,78 @@ TEST_F(UnknownFieldSetTest, Empty) { EXPECT_TRUE(unknown_fields.empty()); } +TEST_F(UnknownFieldSetTest, DeleteSubrange) { + // Exhaustively test the deletion of every possible subrange in arrays of all + // sizes from 0 through 9. + for (int size = 0; size < 10; ++size) { + for (int num = 0; num <= size; ++num) { + for (int start = 0; start < size - num; ++start) { + // Create a set with "size" fields. + UnknownFieldSet unknown; + for (int i = 0; i < size; ++i) { + unknown.AddFixed32(i, i); + } + // Delete the specified subrange. + unknown.DeleteSubrange(start, num); + // Make sure the resulting field values are still correct. + EXPECT_EQ(size - num, unknown.field_count()); + for (int i = 0; i < unknown.field_count(); ++i) { + if (i < start) { + EXPECT_EQ(i, unknown.field(i).fixed32()); + } else { + EXPECT_EQ(i + num, unknown.field(i).fixed32()); + } + } + } + } + } +} + +void CheckDeleteByNumber(const vector& field_numbers, int deleted_number, + const vector& expected_field_nubmers) { + UnknownFieldSet unknown_fields; + for (int i = 0; i < field_numbers.size(); ++i) { + unknown_fields.AddFixed32(field_numbers[i], i); + } + unknown_fields.DeleteByNumber(deleted_number); + ASSERT_EQ(expected_field_nubmers.size(), unknown_fields.field_count()); + for (int i = 0; i < expected_field_nubmers.size(); ++i) { + EXPECT_EQ(expected_field_nubmers[i], + unknown_fields.field(i).number()); + } +} + +#define MAKE_VECTOR(x) vector(x, x + GOOGLE_ARRAYSIZE(x)) +TEST_F(UnknownFieldSetTest, DeleteByNumber) { + CheckDeleteByNumber(vector(), 1, vector()); + static const int kTestFieldNumbers1[] = {1, 2, 3}; + static const int kFieldNumberToDelete1 = 1; + static const int kExpectedFieldNumbers1[] = {2, 3}; + CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers1), kFieldNumberToDelete1, + MAKE_VECTOR(kExpectedFieldNumbers1)); + static const int kTestFieldNumbers2[] = {1, 2, 3}; + static const int kFieldNumberToDelete2 = 2; + static const int kExpectedFieldNumbers2[] = {1, 3}; + CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers2), kFieldNumberToDelete2, + MAKE_VECTOR(kExpectedFieldNumbers2)); + static const int kTestFieldNumbers3[] = {1, 2, 3}; + static const int kFieldNumberToDelete3 = 3; + static const int kExpectedFieldNumbers3[] = {1, 2}; + CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers3), kFieldNumberToDelete3, + MAKE_VECTOR(kExpectedFieldNumbers3)); + static const int kTestFieldNumbers4[] = {1, 2, 1, 4, 1}; + static const int kFieldNumberToDelete4 = 1; + static const int kExpectedFieldNumbers4[] = {2, 4}; + CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers4), kFieldNumberToDelete4, + MAKE_VECTOR(kExpectedFieldNumbers4)); + static const int kTestFieldNumbers5[] = {1, 2, 3, 4, 5}; + static const int kFieldNumberToDelete5 = 6; + static const int kExpectedFieldNumbers5[] = {1, 2, 3, 4, 5}; + CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers5), kFieldNumberToDelete5, + MAKE_VECTOR(kExpectedFieldNumbers5)); +} +#undef MAKE_VECTOR } // namespace + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc index 831a579..9189289 100644 --- a/src/google/protobuf/wire_format.cc +++ b/src/google/protobuf/wire_format.cc @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -48,12 +49,11 @@ #include + namespace google { namespace protobuf { namespace internal { -using internal::WireFormatLite; - namespace { // This function turns out to be convenient when using some macros later. @@ -183,7 +183,8 @@ void WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields, output->WriteVarint32(WireFormatLite::MakeTag(field.number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); output->WriteVarint32(field.length_delimited().size()); - output->WriteString(field.length_delimited()); + output->WriteRawMaybeAliased(field.length_delimited().data(), + field.length_delimited().size()); break; case UnknownField::TYPE_GROUP: output->WriteVarint32(WireFormatLite::MakeTag(field.number(), @@ -239,8 +240,6 @@ void WireFormat::SerializeUnknownMessageSetItems( // The only unknown fields that are allowed to exist in a MessageSet are // messages, which are length-delimited. if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) { - const string& data = field.length_delimited(); - // Start group. output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag); @@ -250,8 +249,7 @@ void WireFormat::SerializeUnknownMessageSetItems( // Write message. output->WriteVarint32(WireFormatLite::kMessageSetMessageTag); - output->WriteVarint32(data.size()); - output->WriteString(data); + field.SerializeLengthDelimitedNoTag(output); // End group. output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag); @@ -268,8 +266,6 @@ uint8* WireFormat::SerializeUnknownMessageSetItemsToArray( // The only unknown fields that are allowed to exist in a MessageSet are // messages, which are length-delimited. if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) { - const string& data = field.length_delimited(); - // Start group. target = io::CodedOutputStream::WriteTagToArray( WireFormatLite::kMessageSetItemStartTag, target); @@ -283,8 +279,7 @@ uint8* WireFormat::SerializeUnknownMessageSetItemsToArray( // Write message. target = io::CodedOutputStream::WriteTagToArray( WireFormatLite::kMessageSetMessageTag, target); - target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target); - target = io::CodedOutputStream::WriteStringToArray(data, target); + target = field.SerializeLengthDelimitedNoTagToArray(target); // End group. target = io::CodedOutputStream::WriteTagToArray( @@ -354,9 +349,10 @@ int WireFormat::ComputeUnknownMessageSetItemsSize( if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) { size += WireFormatLite::kMessageSetItemTagsSize; size += io::CodedOutputStream::VarintSize32(field.number()); - size += io::CodedOutputStream::VarintSize32( - field.length_delimited().size()); - size += field.length_delimited().size(); + + int field_size = field.GetLengthDelimitedSize(); + size += io::CodedOutputStream::VarintSize32(field_size); + size += field_size; } } @@ -417,6 +413,37 @@ bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input, } } +bool WireFormat::SkipMessageSetField(io::CodedInputStream* input, + uint32 field_number, + UnknownFieldSet* unknown_fields) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + return input->ReadString( + unknown_fields->AddLengthDelimited(field_number), length); +} + +bool WireFormat::ParseAndMergeMessageSetField(uint32 field_number, + const FieldDescriptor* field, + Message* message, + io::CodedInputStream* input) { + const Reflection* message_reflection = message->GetReflection(); + if (field == NULL) { + // We store unknown MessageSet extensions as groups. + return SkipMessageSetField( + input, field_number, message_reflection->MutableUnknownFields(message)); + } else if (field->is_repeated() || + field->type() != FieldDescriptor::TYPE_MESSAGE) { + // This shouldn't happen as we only allow optional message extensions to + // MessageSet. + GOOGLE_LOG(ERROR) << "Extensions of MessageSets must be optional messages."; + return false; + } else { + Message* sub_message = message_reflection->MutableMessage( + message, field, input->GetExtensionFactory()); + return WireFormatLite::ReadMessage(input, sub_message); + } +} + bool WireFormat::ParseAndMergeField( uint32 tag, const FieldDescriptor* field, // May be NULL for unknown @@ -568,7 +595,8 @@ bool WireFormat::ParseAndMergeField( case FieldDescriptor::TYPE_STRING: { string value; if (!WireFormatLite::ReadString(input, &value)) return false; - VerifyUTF8String(value.data(), value.length(), PARSE); + VerifyUTF8StringNamedField(value.data(), value.length(), PARSE, + field->name().c_str()); if (field->is_repeated()) { message_reflection->AddString(message, field, value); } else { @@ -632,20 +660,14 @@ bool WireFormat::ParseAndMergeMessageSetItem( // required int32 type_id = 2; // required data message = 3; - // Once we see a type_id, we'll construct a fake tag for this extension - // which is the tag it would have had under the proto2 extensions wire - // format. - uint32 fake_tag = 0; + uint32 last_type_id = 0; // Once we see a type_id, we'll look up the FieldDescriptor for the // extension. const FieldDescriptor* field = NULL; // If we see message data before the type_id, we'll append it to this so - // we can parse it later. This will probably never happen in practice, - // as no MessageSet encoder I know of writes the message before the type ID. - // But, it's technically valid so we should allow it. - // TODO(kenton): Use a Cord instead? Do I care? + // we can parse it later. string message_data; while (true) { @@ -656,8 +678,7 @@ bool WireFormat::ParseAndMergeMessageSetItem( case WireFormatLite::kMessageSetTypeIdTag: { uint32 type_id; if (!input->ReadVarint32(&type_id)) return false; - fake_tag = WireFormatLite::MakeTag( - type_id, WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + last_type_id = type_id; field = message_reflection->FindKnownExtensionByNumber(type_id); if (!message_data.empty()) { @@ -666,8 +687,8 @@ bool WireFormat::ParseAndMergeMessageSetItem( io::ArrayInputStream raw_input(message_data.data(), message_data.size()); io::CodedInputStream sub_input(&raw_input); - if (!ParseAndMergeField(fake_tag, field, message, - &sub_input)) { + if (!ParseAndMergeMessageSetField(last_type_id, field, message, + &sub_input)) { return false; } message_data.clear(); @@ -677,16 +698,20 @@ bool WireFormat::ParseAndMergeMessageSetItem( } case WireFormatLite::kMessageSetMessageTag: { - if (fake_tag == 0) { + if (last_type_id == 0) { // We haven't seen a type_id yet. Append this data to message_data. string temp; uint32 length; if (!input->ReadVarint32(&length)) return false; if (!input->ReadString(&temp, length)) return false; - message_data.append(temp); + io::StringOutputStream output_stream(&message_data); + io::CodedOutputStream coded_output(&output_stream); + coded_output.WriteVarint32(length); + coded_output.WriteString(temp); } else { // Already saw type_id, so we can parse this directly. - if (!ParseAndMergeField(fake_tag, field, message, input)) { + if (!ParseAndMergeMessageSetField(last_type_id, field, message, + input)) { return false; } } @@ -834,7 +859,8 @@ void WireFormat::SerializeFieldWithCachedSizes( message_reflection->GetRepeatedStringReference( message, field, j, &scratch) : message_reflection->GetStringReference(message, field, &scratch); - VerifyUTF8String(value.data(), value.length(), SERIALIZE); + VerifyUTF8StringNamedField(value.data(), value.length(), SERIALIZE, + field->name().c_str()); WireFormatLite::WriteString(field->number(), value, output); break; } @@ -1044,7 +1070,8 @@ int WireFormat::MessageSetItemByteSize( void WireFormat::VerifyUTF8StringFallback(const char* data, int size, - Operation op) { + Operation op, + const char* field_name) { if (!IsStructurallyValidUTF8(data, size)) { const char* operation_str = NULL; switch (op) { @@ -1056,10 +1083,15 @@ void WireFormat::VerifyUTF8StringFallback(const char* data, break; // no default case: have the compiler warn if a case is not covered. } - GOOGLE_LOG(ERROR) << "Encountered string containing invalid UTF-8 data while " - << operation_str - << " protocol buffer. Strings must contain only UTF-8; " - "use the 'bytes' type for raw bytes."; + string quoted_field_name = ""; + if (field_name != NULL) { + quoted_field_name = StringPrintf(" '%s'", field_name); + } + // no space below to avoid double space when the field name is missing. + GOOGLE_LOG(ERROR) << "String field" << quoted_field_name << " contains invalid " + << "UTF-8 data when " << operation_str << " a protocol " + << "buffer. Use the 'bytes' type if you intend to send raw " + << "bytes. "; } } diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h index c753925..0c05c0d 100644 --- a/src/google/protobuf/wire_format.h +++ b/src/google/protobuf/wire_format.h @@ -40,6 +40,7 @@ #define GOOGLE_PROTOBUF_WIRE_FORMAT_H__ #include +#include #include #include #include @@ -78,7 +79,7 @@ class LIBPROTOBUF_EXPORT WireFormat { static inline WireFormatLite::WireType WireTypeForField( const FieldDescriptor* field); - // Given a FieldSescriptor::Type return its WireType + // Given a FieldDescriptor::Type return its WireType static inline WireFormatLite::WireType WireTypeForFieldType( FieldDescriptor::Type type); @@ -179,7 +180,7 @@ class LIBPROTOBUF_EXPORT WireFormat { // of packed repeated fields. static uint32 MakeTag(const FieldDescriptor* field); - // Parse a single field. The input should start out positioned immidately + // Parse a single field. The input should start out positioned immediately // after the tag. static bool ParseAndMergeField( uint32 tag, @@ -227,14 +228,34 @@ class LIBPROTOBUF_EXPORT WireFormat { }; // Verifies that a string field is valid UTF8, logging an error if not. + // This function will not be called by newly generated protobuf code + // but remains present to support existing code. static void VerifyUTF8String(const char* data, int size, Operation op); + // The NamedField variant takes a field name in order to produce an + // informative error message if verification fails. + static void VerifyUTF8StringNamedField(const char* data, + int size, + Operation op, + const char* field_name); private: // Verifies that a string field is valid UTF8, logging an error if not. static void VerifyUTF8StringFallback( const char* data, int size, - Operation op); + Operation op, + const char* field_name); + + // Skip a MessageSet field. + static bool SkipMessageSetField(io::CodedInputStream* input, + uint32 field_number, + UnknownFieldSet* unknown_fields); + + // Parse a MessageSet field. + static bool ParseAndMergeMessageSetField(uint32 field_number, + const FieldDescriptor* field, + Message* message, + io::CodedInputStream* input); @@ -253,7 +274,7 @@ class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper { virtual bool SkipMessage(io::CodedInputStream* input); virtual void SkipUnknownEnum(int field_number, int value); - private: + protected: UnknownFieldSet* unknown_fields_; }; @@ -292,7 +313,18 @@ inline int WireFormat::TagSize(int field_number, FieldDescriptor::Type type) { inline void WireFormat::VerifyUTF8String(const char* data, int size, WireFormat::Operation op) { #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - WireFormat::VerifyUTF8StringFallback(data, size, op); + WireFormat::VerifyUTF8StringFallback(data, size, op, NULL); +#else + // Avoid the compiler warning about unsued variables. + (void)data; (void)size; (void)op; +#endif +} + +inline void WireFormat::VerifyUTF8StringNamedField( + const char* data, int size, WireFormat::Operation op, + const char* field_name) { +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + WireFormat::VerifyUTF8StringFallback(data, size, op, field_name); #endif } diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc index d347d11..d65844d 100644 --- a/src/google/protobuf/wire_format_lite.cc +++ b/src/google/protobuf/wire_format_lite.cc @@ -40,7 +40,7 @@ #include #include #include -#include +#include namespace google { namespace protobuf { @@ -56,10 +56,10 @@ const int WireFormatLite::kMessageSetMessageTag; #endif const int WireFormatLite::kMessageSetItemTagsSize = - io::CodedOutputStream::VarintSize32(kMessageSetItemStartTag) + - io::CodedOutputStream::VarintSize32(kMessageSetItemEndTag) + - io::CodedOutputStream::VarintSize32(kMessageSetTypeIdTag) + - io::CodedOutputStream::VarintSize32(kMessageSetMessageTag); + io::CodedOutputStream::StaticVarintSize32::value + + io::CodedOutputStream::StaticVarintSize32::value + + io::CodedOutputStream::StaticVarintSize32::value + + io::CodedOutputStream::StaticVarintSize32::value; const WireFormatLite::CppType WireFormatLite::kFieldTypeToCppTypeMap[MAX_FIELD_TYPE + 1] = { @@ -153,8 +153,65 @@ bool WireFormatLite::SkipField( } } +bool WireFormatLite::SkipField( + io::CodedInputStream* input, uint32 tag, io::CodedOutputStream* output) { + switch (WireFormatLite::GetTagWireType(tag)) { + case WireFormatLite::WIRETYPE_VARINT: { + uint64 value; + if (!input->ReadVarint64(&value)) return false; + output->WriteVarint32(tag); + output->WriteVarint64(value); + return true; + } + case WireFormatLite::WIRETYPE_FIXED64: { + uint64 value; + if (!input->ReadLittleEndian64(&value)) return false; + output->WriteVarint32(tag); + output->WriteLittleEndian64(value); + return true; + } + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + output->WriteVarint32(tag); + output->WriteVarint32(length); + // TODO(mkilavuz): Provide API to prevent extra string copying. + string temp; + if (!input->ReadString(&temp, length)) return false; + output->WriteString(temp); + return true; + } + case WireFormatLite::WIRETYPE_START_GROUP: { + output->WriteVarint32(tag); + if (!input->IncrementRecursionDepth()) return false; + if (!SkipMessage(input, output)) return false; + input->DecrementRecursionDepth(); + // Check that the ending tag matched the starting tag. + if (!input->LastTagWas(WireFormatLite::MakeTag( + WireFormatLite::GetTagFieldNumber(tag), + WireFormatLite::WIRETYPE_END_GROUP))) { + return false; + } + return true; + } + case WireFormatLite::WIRETYPE_END_GROUP: { + return false; + } + case WireFormatLite::WIRETYPE_FIXED32: { + uint32 value; + if (!input->ReadLittleEndian32(&value)) return false; + output->WriteVarint32(tag); + output->WriteLittleEndian32(value); + return true; + } + default: { + return false; + } + } +} + bool WireFormatLite::SkipMessage(io::CodedInputStream* input) { - while(true) { + while (true) { uint32 tag = input->ReadTag(); if (tag == 0) { // End of input. This is a valid place to end, so return true. @@ -172,6 +229,27 @@ bool WireFormatLite::SkipMessage(io::CodedInputStream* input) { } } +bool WireFormatLite::SkipMessage(io::CodedInputStream* input, + io::CodedOutputStream* output) { + while (true) { + uint32 tag = input->ReadTag(); + if (tag == 0) { + // End of input. This is a valid place to end, so return true. + return true; + } + + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + + if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) { + output->WriteVarint32(tag); + // Must be the end of the message. + return true; + } + + if (!SkipField(input, tag, output)) return false; + } +} + bool FieldSkipper::SkipField( io::CodedInputStream* input, uint32 tag) { return WireFormatLite::SkipField(input, tag); @@ -182,10 +260,25 @@ bool FieldSkipper::SkipMessage(io::CodedInputStream* input) { } void FieldSkipper::SkipUnknownEnum( - int field_number, int value) { + int /* field_number */, int /* value */) { // Nothing. } +bool CodedOutputStreamFieldSkipper::SkipField( + io::CodedInputStream* input, uint32 tag) { + return WireFormatLite::SkipField(input, tag, unknown_fields_); +} + +bool CodedOutputStreamFieldSkipper::SkipMessage(io::CodedInputStream* input) { + return WireFormatLite::SkipMessage(input, unknown_fields_); +} + +void CodedOutputStreamFieldSkipper::SkipUnknownEnum( + int field_number, int value) { + unknown_fields_->WriteVarint32(field_number); + unknown_fields_->WriteVarint64(value); +} + bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input, bool (*is_valid)(int), RepeatedField* values) { @@ -281,15 +374,34 @@ void WireFormatLite::WriteString(int field_number, const string& value, io::CodedOutputStream* output) { // String is for UTF-8 text only WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + GOOGLE_CHECK(value.size() <= kint32max); output->WriteVarint32(value.size()); output->WriteString(value); } +void WireFormatLite::WriteStringMaybeAliased( + int field_number, const string& value, + io::CodedOutputStream* output) { + // String is for UTF-8 text only + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + GOOGLE_CHECK(value.size() <= kint32max); + output->WriteVarint32(value.size()); + output->WriteRawMaybeAliased(value.data(), value.size()); +} void WireFormatLite::WriteBytes(int field_number, const string& value, io::CodedOutputStream* output) { WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + GOOGLE_CHECK(value.size() <= kint32max); output->WriteVarint32(value.size()); output->WriteString(value); } +void WireFormatLite::WriteBytesMaybeAliased( + int field_number, const string& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + GOOGLE_CHECK(value.size() <= kint32max); + output->WriteVarint32(value.size()); + output->WriteRawMaybeAliased(value.data(), value.size()); +} void WireFormatLite::WriteGroup(int field_number, diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h index e3d5b2d..4b6b53e 100644 --- a/src/google/protobuf/wire_format_lite.h +++ b/src/google/protobuf/wire_format_lite.h @@ -41,16 +41,14 @@ #define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ #include +#include #include +#include // for CodedOutputStream::Varint32Size namespace google { namespace protobuf { template class RepeatedField; // repeated_field.h - namespace io { - class CodedInputStream; // coded_stream.h - class CodedOutputStream; // coded_stream.h - } } namespace protobuf { @@ -165,11 +163,22 @@ class LIBPROTOBUF_EXPORT WireFormatLite { // records to an UnknownFieldSet. static bool SkipField(io::CodedInputStream* input, uint32 tag); + // Skips a field value with the given tag. The input should start + // positioned immediately after the tag. Skipped values are recorded to a + // CodedOutputStream. + static bool SkipField(io::CodedInputStream* input, uint32 tag, + io::CodedOutputStream* output); + // Reads and ignores a message from the input. Skipped values are simply // discarded, not recorded anywhere. See WireFormat::SkipMessage() for a // version that records to an UnknownFieldSet. static bool SkipMessage(io::CodedInputStream* input); + // Reads and ignores a message from the input. Skipped values are recorded + // to a CodedOutputStream. + static bool SkipMessage(io::CodedInputStream* input, + io::CodedOutputStream* output); + // This macro does the same thing as WireFormatLite::MakeTag(), but the // result is usable as a compile-time constant, which makes it usable // as a switch case or a template input. WireFormatLite::MakeTag() is more @@ -342,6 +351,10 @@ class LIBPROTOBUF_EXPORT WireFormatLite { static void WriteString(field_number, const string& value, output); static void WriteBytes (field_number, const string& value, output); + static void WriteStringMaybeAliased( + field_number, const string& value, output); + static void WriteBytesMaybeAliased( + field_number, const string& value, output); static void WriteGroup( field_number, const MessageLite& value, output); @@ -477,6 +490,10 @@ class LIBPROTOBUF_EXPORT WireFormatLite { template static inline int MessageSizeNoVirtual(const MessageType& value); + // Given the length of data, calculate the byte size of the data on the + // wire if we encode the data as a length delimited field. + static inline int LengthDelimitedSize(int length); + private: // A helper method for the repeated primitive reader. This method has // optimizations for primitive types that have fixed size on the wire, and @@ -488,6 +505,12 @@ class LIBPROTOBUF_EXPORT WireFormatLite { google::protobuf::io::CodedInputStream* input, RepeatedField* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + // Like ReadRepeatedFixedSizePrimitive but for packed primitive fields. + template + static inline bool ReadPackedFixedSizePrimitive( + google::protobuf::io::CodedInputStream* input, + RepeatedField* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + static const CppType kFieldTypeToCppTypeMap[]; static const WireFormatLite::WireType kWireTypeForFieldType[]; @@ -516,6 +539,24 @@ class LIBPROTOBUF_EXPORT FieldSkipper { virtual void SkipUnknownEnum(int field_number, int value); }; +// Subclass of FieldSkipper which saves skipped fields to a CodedOutputStream. + +class LIBPROTOBUF_EXPORT CodedOutputStreamFieldSkipper : public FieldSkipper { + public: + explicit CodedOutputStreamFieldSkipper(io::CodedOutputStream* unknown_fields) + : unknown_fields_(unknown_fields) {} + virtual ~CodedOutputStreamFieldSkipper() {} + + // implements FieldSkipper ----------------------------------------- + virtual bool SkipField(io::CodedInputStream* input, uint32 tag); + virtual bool SkipMessage(io::CodedInputStream* input); + virtual void SkipUnknownEnum(int field_number, int value); + + protected: + io::CodedOutputStream* unknown_fields_; +}; + + // inline methods ==================================================== inline WireFormatLite::CppType diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h index 3f0d7f8..ca367f5 100644 --- a/src/google/protobuf/wire_format_lite_inl.h +++ b/src/google/protobuf/wire_format_lite_inl.h @@ -36,12 +36,16 @@ #ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ #define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ +#ifdef _MSC_VER +// This is required for min/max on VS2013 only. +#include +#endif + #include #include #include #include #include -#include #include @@ -151,8 +155,8 @@ template <> inline bool WireFormatLite::ReadPrimitive( io::CodedInputStream* input, bool* value) { - uint32 temp; - if (!input->ReadVarint32(&temp)) return false; + uint64 temp; + if (!input->ReadVarint64(&temp)) return false; *value = temp != 0; return true; } @@ -222,10 +226,11 @@ inline const uint8* WireFormatLite::ReadPrimitiveFromArray< } template -inline bool WireFormatLite::ReadRepeatedPrimitive(int, // tag_size, unused - uint32 tag, - io::CodedInputStream* input, - RepeatedField* values) { +inline bool WireFormatLite::ReadRepeatedPrimitive( + int, // tag_size, unused. + uint32 tag, + io::CodedInputStream* input, + RepeatedField* values) { CType value; if (!ReadPrimitive(input, &value)) return false; values->Add(value); @@ -285,7 +290,7 @@ inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive( return true; } -// Specializations of ReadRepeatedPrimitive for the fixed size types, which use +// Specializations of ReadRepeatedPrimitive for the fixed size types, which use // the optimized code path. #define READ_REPEATED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \ template <> \ @@ -300,12 +305,12 @@ inline bool WireFormatLite::ReadRepeatedPrimitive< \ tag_size, tag, input, values); \ } -READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32); -READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64); -READ_REPEATED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32); -READ_REPEATED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64); -READ_REPEATED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT); -READ_REPEATED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE); +READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE) #undef READ_REPEATED_FIXED_SIZE_PRIMITIVE @@ -335,6 +340,86 @@ inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input, } template +inline bool WireFormatLite::ReadPackedFixedSizePrimitive( + io::CodedInputStream* input, RepeatedField* values) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + const uint32 old_entries = values->size(); + const uint32 new_entries = length / sizeof(CType); + const uint32 new_bytes = new_entries * sizeof(CType); + if (new_bytes != length) return false; + // We would *like* to pre-allocate the buffer to write into (for + // speed), but *must* avoid performing a very large allocation due + // to a malicious user-supplied "length" above. So we have a fast + // path that pre-allocates when the "length" is less than a bound. + // We determine the bound by calling BytesUntilTotalBytesLimit() and + // BytesUntilLimit(). These return -1 to mean "no limit set". + // There are four cases: + // TotalBytesLimit Limit + // -1 -1 Use slow path. + // -1 >= 0 Use fast path if length <= Limit. + // >= 0 -1 Use slow path. + // >= 0 >= 0 Use fast path if length <= min(both limits). + int64 bytes_limit = input->BytesUntilTotalBytesLimit(); + if (bytes_limit == -1) { + bytes_limit = input->BytesUntilLimit(); + } else { + bytes_limit = + min(bytes_limit, static_cast(input->BytesUntilLimit())); + } + if (bytes_limit >= new_bytes) { + // Fast-path that pre-allocates *values to the final size. +#if defined(PROTOBUF_LITTLE_ENDIAN) + values->Resize(old_entries + new_entries, 0); + // values->mutable_data() may change after Resize(), so do this after: + void* dest = reinterpret_cast(values->mutable_data() + old_entries); + if (!input->ReadRaw(dest, new_bytes)) { + values->Truncate(old_entries); + return false; + } +#else + values->Reserve(old_entries + new_entries); + CType value; + for (int i = 0; i < new_entries; ++i) { + if (!ReadPrimitive(input, &value)) return false; + values->AddAlreadyReserved(value); + } +#endif + } else { + // This is the slow-path case where "length" may be too large to + // safely allocate. We read as much as we can into *values + // without pre-allocating "length" bytes. + CType value; + for (int i = 0; i < new_entries; ++i) { + if (!ReadPrimitive(input, &value)) return false; + values->Add(value); + } + } + return true; +} + +// Specializations of ReadPackedPrimitive for the fixed size types, which use +// an optimized code path. +#define READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \ +template <> \ +inline bool WireFormatLite::ReadPackedPrimitive< \ + CPPTYPE, WireFormatLite::DECLARED_TYPE>( \ + io::CodedInputStream* input, \ + RepeatedField* values) { \ + return ReadPackedFixedSizePrimitive< \ + CPPTYPE, WireFormatLite::DECLARED_TYPE>(input, values); \ +} + +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32); +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64); +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32); +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64); +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT); +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE); + +#undef READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE + +template bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input, RepeatedField* values) { return ReadPackedPrimitive(input, values); @@ -368,12 +453,24 @@ inline bool WireFormatLite::ReadMessage(io::CodedInputStream* input, return true; } -template -inline bool WireFormatLite::ReadGroupNoVirtual(int field_number, - io::CodedInputStream* input, - MessageType* value) { +// We name the template parameter something long and extremely unlikely to occur +// elsewhere because a *qualified* member access expression designed to avoid +// virtual dispatch, C++03 [basic.lookup.classref] 3.4.5/4 requires that the +// name of the qualifying class to be looked up both in the context of the full +// expression (finding the template parameter) and in the context of the object +// whose member we are accessing. This could potentially find a nested type +// within that object. The standard goes on to require these names to refer to +// the same entity, which this collision would violate. The lack of a safe way +// to avoid this collision appears to be a defect in the standard, but until it +// is corrected, we choose the name to avoid accidental collisions. +template +inline bool WireFormatLite::ReadGroupNoVirtual( + int field_number, io::CodedInputStream* input, + MessageType_WorkAroundCppLookupDefect* value) { if (!input->IncrementRecursionDepth()) return false; - if (!value->MessageType::MergePartialFromCodedStream(input)) return false; + if (!value-> + MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) + return false; input->DecrementRecursionDepth(); // Make sure the last thing read was an end tag for this group. if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { @@ -381,14 +478,16 @@ inline bool WireFormatLite::ReadGroupNoVirtual(int field_number, } return true; } -template -inline bool WireFormatLite::ReadMessageNoVirtual(io::CodedInputStream* input, - MessageType* value) { +template +inline bool WireFormatLite::ReadMessageNoVirtual( + io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) { uint32 length; if (!input->ReadVarint32(&length)) return false; if (!input->IncrementRecursionDepth()) return false; io::CodedInputStream::Limit limit = input->PushLimit(length); - if (!value->MessageType::MergePartialFromCodedStream(input)) return false; + if (!value-> + MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) + return false; // Make sure that parsing stopped when the limit was hit, not at an endgroup // tag. if (!input->ConsumedEntireMessage()) return false; @@ -461,21 +560,24 @@ inline void WireFormatLite::WriteEnumNoTag(int value, output->WriteVarint32SignExtended(value); } -template -inline void WireFormatLite::WriteGroupNoVirtual(int field_number, - const MessageType& value, - io::CodedOutputStream* output) { +// See comment on ReadGroupNoVirtual to understand the need for this template +// parameter name. +template +inline void WireFormatLite::WriteGroupNoVirtual( + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + io::CodedOutputStream* output) { WriteTag(field_number, WIRETYPE_START_GROUP, output); - value.MessageType::SerializeWithCachedSizes(output); + value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output); WriteTag(field_number, WIRETYPE_END_GROUP, output); } -template -inline void WireFormatLite::WriteMessageNoVirtual(int field_number, - const MessageType& value, - io::CodedOutputStream* output) { +template +inline void WireFormatLite::WriteMessageNoVirtual( + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + io::CodedOutputStream* output) { WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(value.MessageType::GetCachedSize()); - value.MessageType::SerializeWithCachedSizes(output); + output->WriteVarint32( + value.MessageType_WorkAroundCppLookupDefect::GetCachedSize()); + value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output); } // =================================================================== @@ -644,15 +746,13 @@ inline uint8* WireFormatLite::WriteStringToArray(int field_number, // WriteString() to avoid code duplication. If the implementations become // different, you will need to update that usage. target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); - target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target); - return io::CodedOutputStream::WriteStringToArray(value, target); + return io::CodedOutputStream::WriteStringWithSizeToArray(value, target); } inline uint8* WireFormatLite::WriteBytesToArray(int field_number, const string& value, uint8* target) { target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); - target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target); - return io::CodedOutputStream::WriteStringToArray(value, target); + return io::CodedOutputStream::WriteStringWithSizeToArray(value, target); } @@ -672,20 +772,26 @@ inline uint8* WireFormatLite::WriteMessageToArray(int field_number, return value.SerializeWithCachedSizesToArray(target); } -template +// See comment on ReadGroupNoVirtual to understand the need for this template +// parameter name. +template inline uint8* WireFormatLite::WriteGroupNoVirtualToArray( - int field_number, const MessageType& value, uint8* target) { + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + uint8* target) { target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); - target = value.MessageType::SerializeWithCachedSizesToArray(target); + target = value.MessageType_WorkAroundCppLookupDefect + ::SerializeWithCachedSizesToArray(target); return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); } -template +template inline uint8* WireFormatLite::WriteMessageNoVirtualToArray( - int field_number, const MessageType& value, uint8* target) { + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + uint8* target) { target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); target = io::CodedOutputStream::WriteVarint32ToArray( - value.MessageType::GetCachedSize(), target); - return value.MessageType::SerializeWithCachedSizesToArray(target); + value.MessageType_WorkAroundCppLookupDefect::GetCachedSize(), target); + return value.MessageType_WorkAroundCppLookupDefect + ::SerializeWithCachedSizesToArray(target); } // =================================================================== @@ -726,18 +832,25 @@ inline int WireFormatLite::GroupSize(const MessageLite& value) { return value.ByteSize(); } inline int WireFormatLite::MessageSize(const MessageLite& value) { - int size = value.ByteSize(); - return io::CodedOutputStream::VarintSize32(size) + size; + return LengthDelimitedSize(value.ByteSize()); } -template -inline int WireFormatLite::GroupSizeNoVirtual(const MessageType& value) { - return value.MessageType::ByteSize(); +// See comment on ReadGroupNoVirtual to understand the need for this template +// parameter name. +template +inline int WireFormatLite::GroupSizeNoVirtual( + const MessageType_WorkAroundCppLookupDefect& value) { + return value.MessageType_WorkAroundCppLookupDefect::ByteSize(); } -template -inline int WireFormatLite::MessageSizeNoVirtual(const MessageType& value) { - int size = value.MessageType::ByteSize(); - return io::CodedOutputStream::VarintSize32(size) + size; +template +inline int WireFormatLite::MessageSizeNoVirtual( + const MessageType_WorkAroundCppLookupDefect& value) { + return LengthDelimitedSize( + value.MessageType_WorkAroundCppLookupDefect::ByteSize()); +} + +inline int WireFormatLite::LengthDelimitedSize(int length) { + return io::CodedOutputStream::VarintSize32(length) + length; } } // namespace internal diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc index 867970c..3a44aaf 100644 --- a/src/google/protobuf/wire_format_unittest.cc +++ b/src/google/protobuf/wire_format_unittest.cc @@ -44,7 +44,7 @@ #include #include #include -#include +#include namespace google { namespace protobuf { @@ -175,6 +175,43 @@ TEST(WireFormatTest, ParsePackedExtensions) { TestUtil::ExpectPackedExtensionsSet(dest); } +TEST(WireFormatTest, ParseOneof) { + unittest::TestOneof2 source, dest; + string data; + + // Serialize using the generated code. + TestUtil::SetOneof1(&source); + source.SerializeToString(&data); + + // Parse using WireFormat. + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + WireFormat::ParseAndMergePartial(&input, &dest); + + // Check. + TestUtil::ExpectOneofSet1(dest); +} + +TEST(WireFormatTest, OneofOnlySetLast) { + unittest::TestOneofBackwardsCompatible source; + unittest::TestOneof oneof_dest; + string data; + + // Set two fields + source.set_foo_int(100); + source.set_foo_string("101"); + + // Serialize and parse to oneof message. + source.SerializeToString(&data); + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + WireFormat::ParseAndMergePartial(&input, &oneof_dest); + + // Only the last field is set. + EXPECT_FALSE(oneof_dest.has_foo_int()); + EXPECT_TRUE(oneof_dest.has_foo_string()); +} + TEST(WireFormatTest, ByteSize) { unittest::TestAllTypes message; TestUtil::SetAllFields(&message); @@ -217,6 +254,18 @@ TEST(WireFormatTest, ByteSizePackedExtensions) { EXPECT_EQ(0, WireFormat::ByteSize(message)); } +TEST(WireFormatTest, ByteSizeOneof) { + unittest::TestOneof2 message; + TestUtil::SetOneof1(&message); + + EXPECT_EQ(message.ByteSize(), + WireFormat::ByteSize(message)); + message.Clear(); + + EXPECT_EQ(0, message.ByteSize()); + EXPECT_EQ(0, WireFormat::ByteSize(message)); +} + TEST(WireFormatTest, Serialize) { unittest::TestAllTypes message; string generated_data; @@ -311,6 +360,36 @@ TEST(WireFormatTest, SerializeFieldsAndExtensions) { TestUtil::ExpectAllFieldsAndExtensionsInOrder(generated_data); } +TEST(WireFormatTest, SerializeOneof) { + unittest::TestOneof2 message; + string generated_data; + string dynamic_data; + + TestUtil::SetOneof1(&message); + int size = message.ByteSize(); + + // Serialize using the generated code. + { + io::StringOutputStream raw_output(&generated_data); + io::CodedOutputStream output(&raw_output); + message.SerializeWithCachedSizes(&output); + ASSERT_FALSE(output.HadError()); + } + + // Serialize using WireFormat. + { + io::StringOutputStream raw_output(&dynamic_data); + io::CodedOutputStream output(&raw_output); + WireFormat::SerializeWithCachedSizes(message, size, &output); + ASSERT_FALSE(output.HadError()); + } + + // Should be the same. + // Don't use EXPECT_EQ here because we're comparing raw binary data and + // we really don't want it dumped to stdout on failure. + EXPECT_TRUE(dynamic_data == generated_data); +} + TEST(WireFormatTest, ParseMultipleExtensionRanges) { // Make sure we can parse a message that contains multiple extensions ranges. unittest::TestFieldOrderings source; @@ -480,6 +559,54 @@ TEST(WireFormatTest, ParseMessageSet) { EXPECT_EQ(message_set.DebugString(), dynamic_message_set.DebugString()); } +TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) { + string data; + { + unittest::TestMessageSetExtension1 message; + message.set_i(123); + // Build a MessageSet manually with its message content put before its + // type_id. + io::StringOutputStream output_stream(&data); + io::CodedOutputStream coded_output(&output_stream); + coded_output.WriteTag(WireFormatLite::kMessageSetItemStartTag); + // Write the message content first. + WireFormatLite::WriteTag(WireFormatLite::kMessageSetMessageNumber, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + &coded_output); + coded_output.WriteVarint32(message.ByteSize()); + message.SerializeWithCachedSizes(&coded_output); + // Write the type id. + uint32 type_id = message.GetDescriptor()->extension(0)->number(); + WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber, + type_id, &coded_output); + coded_output.WriteTag(WireFormatLite::kMessageSetItemEndTag); + } + { + unittest::TestMessageSet message_set; + ASSERT_TRUE(message_set.ParseFromString(data)); + + EXPECT_EQ(123, message_set.GetExtension( + unittest::TestMessageSetExtension1::message_set_extension).i()); + } + { + // Test parse the message via Reflection. + unittest::TestMessageSet message_set; + io::CodedInputStream input( + reinterpret_cast(data.data()), data.size()); + EXPECT_TRUE(WireFormat::ParseAndMergePartial(&input, &message_set)); + EXPECT_TRUE(input.ConsumedEntireMessage()); + + EXPECT_EQ(123, message_set.GetExtension( + unittest::TestMessageSetExtension1::message_set_extension).i()); + } +} + +TEST(WireFormatTest, ParseBrokenMessageSet) { + unittest::TestMessageSet message_set; + string input("goodbye"); // Invalid wire format data. + EXPECT_FALSE(message_set.ParseFromString(input)); +} + TEST(WireFormatTest, RecursionLimit) { unittest::TestRecursiveMessage message; message.mutable_a()->mutable_a()->mutable_a()->mutable_a()->set_i(1); @@ -639,6 +766,34 @@ TEST(WireFormatTest, RepeatedScalarsDifferentTagSizes) { EXPECT_EQ(msg1.DebugString(), msg2.DebugString()); } +TEST(WireFormatTest, CompatibleTypes) { + const int64 data = 0x100000000; + unittest::Int64Message msg1; + msg1.set_data(data); + string serialized; + msg1.SerializeToString(&serialized); + + // Test int64 is compatible with bool + unittest::BoolMessage msg2; + ASSERT_TRUE(msg2.ParseFromString(serialized)); + ASSERT_EQ(static_cast(data), msg2.data()); + + // Test int64 is compatible with uint64 + unittest::Uint64Message msg3; + ASSERT_TRUE(msg3.ParseFromString(serialized)); + ASSERT_EQ(static_cast(data), msg3.data()); + + // Test int64 is compatible with int32 + unittest::Int32Message msg4; + ASSERT_TRUE(msg4.ParseFromString(serialized)); + ASSERT_EQ(static_cast(data), msg4.data()); + + // Test int64 is compatible with uint32 + unittest::Uint32Message msg5; + ASSERT_TRUE(msg5.ParseFromString(serialized)); + ASSERT_EQ(static_cast(data), msg5.data()); +} + class WireFormatInvalidInputTest : public testing::Test { protected: // Make a serialized TestAllTypes in which the field optional_nested_message @@ -800,7 +955,20 @@ bool ReadMessage(const string &wire_buffer, T *message) { return message->ParseFromArray(wire_buffer.data(), wire_buffer.size()); } -TEST(Utf8ValidationTest, WriteInvalidUTF8String) { +bool StartsWith(const string& s, const string& prefix) { + return s.substr(0, prefix.length()) == prefix; +} + +class Utf8ValidationTest : public ::testing::Test { + protected: + Utf8ValidationTest() {} + virtual ~Utf8ValidationTest() {} + virtual void SetUp() { + } + +}; + +TEST_F(Utf8ValidationTest, WriteInvalidUTF8String) { string wire_buffer; protobuf_unittest::OneString input; vector errors; @@ -811,17 +979,17 @@ TEST(Utf8ValidationTest, WriteInvalidUTF8String) { } #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED ASSERT_EQ(1, errors.size()); - EXPECT_EQ("Encountered string containing invalid UTF-8 data while " - "serializing protocol buffer. Strings must contain only UTF-8; " - "use the 'bytes' type for raw bytes.", - errors[0]); - + EXPECT_TRUE(StartsWith(errors[0], + "String field 'data' contains invalid UTF-8 data when " + "serializing a protocol buffer. Use the " + "'bytes' type if you intend to send raw bytes.")); #else ASSERT_EQ(0, errors.size()); #endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED } -TEST(Utf8ValidationTest, ReadInvalidUTF8String) { + +TEST_F(Utf8ValidationTest, ReadInvalidUTF8String) { string wire_buffer; protobuf_unittest::OneString input; WriteMessage(kInvalidUTF8String, &input, &wire_buffer); @@ -834,17 +1002,18 @@ TEST(Utf8ValidationTest, ReadInvalidUTF8String) { } #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED ASSERT_EQ(1, errors.size()); - EXPECT_EQ("Encountered string containing invalid UTF-8 data while " - "parsing protocol buffer. Strings must contain only UTF-8; " - "use the 'bytes' type for raw bytes.", - errors[0]); + EXPECT_TRUE(StartsWith(errors[0], + "String field 'data' contains invalid UTF-8 data when " + "parsing a protocol buffer. Use the " + "'bytes' type if you intend to send raw bytes.")); #else ASSERT_EQ(0, errors.size()); #endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED } -TEST(Utf8ValidationTest, WriteValidUTF8String) { + +TEST_F(Utf8ValidationTest, WriteValidUTF8String) { string wire_buffer; protobuf_unittest::OneString input; vector errors; @@ -856,7 +1025,7 @@ TEST(Utf8ValidationTest, WriteValidUTF8String) { ASSERT_EQ(0, errors.size()); } -TEST(Utf8ValidationTest, ReadValidUTF8String) { +TEST_F(Utf8ValidationTest, ReadValidUTF8String) { string wire_buffer; protobuf_unittest::OneString input; WriteMessage(kValidUTF8String, &input, &wire_buffer); @@ -872,7 +1041,7 @@ TEST(Utf8ValidationTest, ReadValidUTF8String) { } // Bytes: anything can pass as bytes, use invalid UTF-8 string to test -TEST(Utf8ValidationTest, WriteArbitraryBytes) { +TEST_F(Utf8ValidationTest, WriteArbitraryBytes) { string wire_buffer; protobuf_unittest::OneBytes input; vector errors; @@ -884,7 +1053,7 @@ TEST(Utf8ValidationTest, WriteArbitraryBytes) { ASSERT_EQ(0, errors.size()); } -TEST(Utf8ValidationTest, ReadArbitraryBytes) { +TEST_F(Utf8ValidationTest, ReadArbitraryBytes) { string wire_buffer; protobuf_unittest::OneBytes input; WriteMessage(kInvalidUTF8String, &input, &wire_buffer); @@ -899,6 +1068,52 @@ TEST(Utf8ValidationTest, ReadArbitraryBytes) { EXPECT_EQ(input.data(), output.data()); } +TEST_F(Utf8ValidationTest, ParseRepeatedString) { + protobuf_unittest::MoreBytes input; + input.add_data(kValidUTF8String); + input.add_data(kInvalidUTF8String); + input.add_data(kInvalidUTF8String); + string wire_buffer = input.SerializeAsString(); + + protobuf_unittest::MoreString output; + vector errors; + { + ScopedMemoryLog log; + ReadMessage(wire_buffer, &output); + errors = log.GetMessages(ERROR); + } +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + ASSERT_EQ(2, errors.size()); +#else + ASSERT_EQ(0, errors.size()); +#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + EXPECT_EQ(wire_buffer, output.SerializeAsString()); +} + +// Test the old VerifyUTF8String() function, which may still be called by old +// generated code. +TEST_F(Utf8ValidationTest, OldVerifyUTF8String) { + string data(kInvalidUTF8String); + + vector errors; + { + ScopedMemoryLog log; + WireFormat::VerifyUTF8String(data.data(), data.size(), + WireFormat::SERIALIZE); + errors = log.GetMessages(ERROR); + } +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + ASSERT_EQ(1, errors.size()); + EXPECT_TRUE(StartsWith(errors[0], + "String field contains invalid UTF-8 data when " + "serializing a protocol buffer. Use the " + "'bytes' type if you intend to send raw bytes.")); +#else + ASSERT_EQ(0, errors.size()); +#endif +} + + } // namespace } // namespace internal } // namespace protobuf diff --git a/vsprojects/extract_includes.bat b/vsprojects/extract_includes.bat index 5e513d7..beab8c4 100755 --- a/vsprojects/extract_includes.bat +++ b/vsprojects/extract_includes.bat @@ -7,13 +7,19 @@ md include\google\protobuf\compiler md include\google\protobuf\compiler\cpp md include\google\protobuf\compiler\java md include\google\protobuf\compiler\python +copy ..\src\google\protobuf\stubs\atomicops.h include\google\protobuf\stubs\atomicops.h +copy ..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.h include\google\protobuf\stubs\atomicops_internals_x86_msvc.h copy ..\src\google\protobuf\stubs\common.h include\google\protobuf\stubs\common.h copy ..\src\google\protobuf\stubs\once.h include\google\protobuf\stubs\once.h +copy ..\src\google\protobuf\stubs\platform_macros.h include\google\protobuf\stubs\platform_macros.h +copy ..\src\google\protobuf\stubs\template_util.h include\google\protobuf\stubs\template_util.h +copy ..\src\google\protobuf\stubs\type_traits.h include\google\protobuf\stubs\type_traits.h copy ..\src\google\protobuf\descriptor.h include\google\protobuf\descriptor.h copy ..\src\google\protobuf\descriptor.pb.h include\google\protobuf\descriptor.pb.h copy ..\src\google\protobuf\descriptor_database.h include\google\protobuf\descriptor_database.h copy ..\src\google\protobuf\dynamic_message.h include\google\protobuf\dynamic_message.h copy ..\src\google\protobuf\extension_set.h include\google\protobuf\extension_set.h +copy ..\src\google\protobuf\generated_enum_reflection.h include\google\protobuf\generated_enum_reflection.h copy ..\src\google\protobuf\generated_message_util.h include\google\protobuf\generated_message_util.h copy ..\src\google\protobuf\generated_message_reflection.h include\google\protobuf\generated_message_reflection.h copy ..\src\google\protobuf\message.h include\google\protobuf\message.h @@ -29,6 +35,7 @@ copy ..\src\google\protobuf\wire_format_lite_inl.h include\google\protobuf\wire_ copy ..\src\google\protobuf\io\coded_stream.h include\google\protobuf\io\coded_stream.h copy ..\src\google\protobuf\io\gzip_stream.h include\google\protobuf\io\gzip_stream.h copy ..\src\google\protobuf\io\printer.h include\google\protobuf\io\printer.h +copy ..\src\google\protobuf\io\strtod.h include\google\protobuf\io\strtod.h copy ..\src\google\protobuf\io\tokenizer.h include\google\protobuf\io\tokenizer.h copy ..\src\google\protobuf\io\zero_copy_stream.h include\google\protobuf\io\zero_copy_stream.h copy ..\src\google\protobuf\io\zero_copy_stream_impl.h include\google\protobuf\io\zero_copy_stream_impl.h @@ -40,3 +47,4 @@ copy ..\src\google\protobuf\compiler\parser.h include\google\protobuf\compiler\p copy ..\src\google\protobuf\compiler\cpp\cpp_generator.h include\google\protobuf\compiler\cpp\cpp_generator.h copy ..\src\google\protobuf\compiler\java\java_generator.h include\google\protobuf\compiler\java\java_generator.h copy ..\src\google\protobuf\compiler\python\python_generator.h include\google\protobuf\compiler\python\python_generator.h +copy ..\src\google\protobuf\compiler\plugin.h include\google\protobuf\compiler\plugin.h diff --git a/vsprojects/libprotobuf-lite.vcproj b/vsprojects/libprotobuf-lite.vcproj index 8197699..06b1598 100644 --- a/vsprojects/libprotobuf-lite.vcproj +++ b/vsprojects/libprotobuf-lite.vcproj @@ -1,7 +1,7 @@  + + + + + + + + + + + + + + diff --git a/vsprojects/libprotobuf.vcproj b/vsprojects/libprotobuf.vcproj index 7b8111f..1a488f7 100644 --- a/vsprojects/libprotobuf.vcproj +++ b/vsprojects/libprotobuf.vcproj @@ -1,7 +1,7 @@ - + + + @@ -204,7 +208,7 @@ > + + + + + + @@ -240,7 +256,19 @@ > + + + + + + + + @@ -427,6 +459,10 @@ RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.cc" > + + diff --git a/vsprojects/libprotoc.vcproj b/vsprojects/libprotoc.vcproj index 81063d3..ccbc0b3 100644 --- a/vsprojects/libprotoc.vcproj +++ b/vsprojects/libprotoc.vcproj @@ -1,406 +1,466 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vsprojects/lite-test.vcproj b/vsprojects/lite-test.vcproj index 0887cf1..0314b36 100644 --- a/vsprojects/lite-test.vcproj +++ b/vsprojects/lite-test.vcproj @@ -1,7 +1,7 @@  + + + + + + + + + + + + diff --git a/vsprojects/protobuf.sln b/vsprojects/protobuf.sln index bac0055..567dee6 100644 --- a/vsprojects/protobuf.sln +++ b/vsprojects/protobuf.sln @@ -1,92 +1,92 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotobuf", "libprotobuf.vcproj", "{3E283F37-A4ED-41B7-A3E6-A2D89D131A30}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotoc", "libprotoc.vcproj", "{B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}" - ProjectSection(ProjectDependencies) = postProject - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "protoc", "protoc.vcproj", "{1738D5F6-ED1E-47E0-B2F0-456864B93C1E}" - ProjectSection(ProjectDependencies) = postProject - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests.vcproj", "{4DF72760-C055-40A5-A77E-30A17E2AC2DB}" - ProjectSection(ProjectDependencies) = postProject - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} - {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} = {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} - {3AF54C8A-10BF-4332-9147-F68ED9862032} = {3AF54C8A-10BF-4332-9147-F68ED9862032} - {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32} = {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32} - {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} = {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "..\gtest\msvc\gtest.vcproj", "{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_main", "..\gtest\msvc\gtest_main.vcproj", "{3AF54C8A-10BF-4332-9147-F68ED9862032}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotobuf-lite", "libprotobuf-lite.vcproj", "{49EA010D-706F-4BE2-A397-77854B72A040}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lite-test", "lite-test.vcproj", "{12015ACE-42BE-4952-A5A0-44A9A46908E2}" - ProjectSection(ProjectDependencies) = postProject - {49EA010D-706F-4BE2-A397-77854B72A040} = {49EA010D-706F-4BE2-A397-77854B72A040} - {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} = {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_plugin", "test_plugin.vcproj", "{CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}" - ProjectSection(ProjectDependencies) = postProject - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} - {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} = {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|Win32.ActiveCfg = Debug|Win32 - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|Win32.Build.0 = Debug|Win32 - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|Win32.ActiveCfg = Release|Win32 - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|Win32.Build.0 = Release|Win32 - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Debug|Win32.ActiveCfg = Debug|Win32 - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Debug|Win32.Build.0 = Debug|Win32 - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Release|Win32.ActiveCfg = Release|Win32 - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Release|Win32.Build.0 = Release|Win32 - {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Debug|Win32.ActiveCfg = Debug|Win32 - {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Debug|Win32.Build.0 = Debug|Win32 - {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Release|Win32.ActiveCfg = Release|Win32 - {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Release|Win32.Build.0 = Release|Win32 - {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Debug|Win32.ActiveCfg = Debug|Win32 - {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Debug|Win32.Build.0 = Debug|Win32 - {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Release|Win32.ActiveCfg = Release|Win32 - {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Release|Win32.Build.0 = Release|Win32 - {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug|Win32.ActiveCfg = Debug|Win32 - {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug|Win32.Build.0 = Debug|Win32 - {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release|Win32.ActiveCfg = Release|Win32 - {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release|Win32.Build.0 = Release|Win32 - {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug|Win32.ActiveCfg = Debug|Win32 - {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug|Win32.Build.0 = Debug|Win32 - {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release|Win32.ActiveCfg = Release|Win32 - {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release|Win32.Build.0 = Release|Win32 - {49EA010D-706F-4BE2-A397-77854B72A040}.Debug|Win32.ActiveCfg = Debug|Win32 - {49EA010D-706F-4BE2-A397-77854B72A040}.Debug|Win32.Build.0 = Debug|Win32 - {49EA010D-706F-4BE2-A397-77854B72A040}.Release|Win32.ActiveCfg = Release|Win32 - {49EA010D-706F-4BE2-A397-77854B72A040}.Release|Win32.Build.0 = Release|Win32 - {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Debug|Win32.ActiveCfg = Debug|Win32 - {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Debug|Win32.Build.0 = Debug|Win32 - {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Release|Win32.ActiveCfg = Release|Win32 - {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Release|Win32.Build.0 = Release|Win32 - {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}.Debug|Win32.ActiveCfg = Debug|Win32 - {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}.Debug|Win32.Build.0 = Debug|Win32 - {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}.Release|Win32.ActiveCfg = Release|Win32 - {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotobuf", "libprotobuf.vcproj", "{3E283F37-A4ED-41B7-A3E6-A2D89D131A30}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotoc", "libprotoc.vcproj", "{B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}" + ProjectSection(ProjectDependencies) = postProject + {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "protoc", "protoc.vcproj", "{1738D5F6-ED1E-47E0-B2F0-456864B93C1E}" + ProjectSection(ProjectDependencies) = postProject + {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} + {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests.vcproj", "{4DF72760-C055-40A5-A77E-30A17E2AC2DB}" + ProjectSection(ProjectDependencies) = postProject + {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} + {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} + {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} = {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} + {3AF54C8A-10BF-4332-9147-F68ED9862032} = {3AF54C8A-10BF-4332-9147-F68ED9862032} + {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32} = {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32} + {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} = {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "..\gtest\msvc\gtest.vcproj", "{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_main", "..\gtest\msvc\gtest_main.vcproj", "{3AF54C8A-10BF-4332-9147-F68ED9862032}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotobuf-lite", "libprotobuf-lite.vcproj", "{49EA010D-706F-4BE2-A397-77854B72A040}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lite-test", "lite-test.vcproj", "{12015ACE-42BE-4952-A5A0-44A9A46908E2}" + ProjectSection(ProjectDependencies) = postProject + {49EA010D-706F-4BE2-A397-77854B72A040} = {49EA010D-706F-4BE2-A397-77854B72A040} + {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} = {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_plugin", "test_plugin.vcproj", "{CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}" + ProjectSection(ProjectDependencies) = postProject + {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} + {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} + {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} = {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|Win32.ActiveCfg = Debug|Win32 + {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|Win32.Build.0 = Debug|Win32 + {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|Win32.ActiveCfg = Release|Win32 + {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|Win32.Build.0 = Release|Win32 + {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Debug|Win32.ActiveCfg = Debug|Win32 + {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Debug|Win32.Build.0 = Debug|Win32 + {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Release|Win32.ActiveCfg = Release|Win32 + {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Release|Win32.Build.0 = Release|Win32 + {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Debug|Win32.ActiveCfg = Debug|Win32 + {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Debug|Win32.Build.0 = Debug|Win32 + {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Release|Win32.ActiveCfg = Release|Win32 + {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Release|Win32.Build.0 = Release|Win32 + {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Debug|Win32.ActiveCfg = Debug|Win32 + {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Debug|Win32.Build.0 = Debug|Win32 + {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Release|Win32.ActiveCfg = Release|Win32 + {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Release|Win32.Build.0 = Release|Win32 + {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug|Win32.ActiveCfg = Debug|Win32 + {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug|Win32.Build.0 = Debug|Win32 + {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release|Win32.ActiveCfg = Release|Win32 + {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release|Win32.Build.0 = Release|Win32 + {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug|Win32.Build.0 = Debug|Win32 + {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release|Win32.ActiveCfg = Release|Win32 + {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release|Win32.Build.0 = Release|Win32 + {49EA010D-706F-4BE2-A397-77854B72A040}.Debug|Win32.ActiveCfg = Debug|Win32 + {49EA010D-706F-4BE2-A397-77854B72A040}.Debug|Win32.Build.0 = Debug|Win32 + {49EA010D-706F-4BE2-A397-77854B72A040}.Release|Win32.ActiveCfg = Release|Win32 + {49EA010D-706F-4BE2-A397-77854B72A040}.Release|Win32.Build.0 = Release|Win32 + {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Debug|Win32.ActiveCfg = Debug|Win32 + {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Debug|Win32.Build.0 = Debug|Win32 + {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Release|Win32.ActiveCfg = Release|Win32 + {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Release|Win32.Build.0 = Release|Win32 + {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}.Debug|Win32.ActiveCfg = Debug|Win32 + {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}.Debug|Win32.Build.0 = Debug|Win32 + {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}.Release|Win32.ActiveCfg = Release|Win32 + {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vsprojects/protoc.vcproj b/vsprojects/protoc.vcproj index a0ca63e..17e8474 100644 --- a/vsprojects/protoc.vcproj +++ b/vsprojects/protoc.vcproj @@ -1,192 +1,192 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vsprojects/test_plugin.vcproj b/vsprojects/test_plugin.vcproj index cfe387f..2dcf2ad 100755 --- a/vsprojects/test_plugin.vcproj +++ b/vsprojects/test_plugin.vcproj @@ -1,20 +1,20 @@ - - - - - - - + + + + + + + + + @@ -263,6 +267,10 @@ > + + @@ -279,6 +287,10 @@ > + + @@ -339,10 +351,26 @@ > + + + + + + + + @@ -375,6 +403,10 @@ > + + @@ -524,6 +556,30 @@ + + + + + + + +